C ++模板专业化问题

时间:2009-05-26 12:58:09

标签: c++ templates metaprogramming

我需要一个C ++模板,给定一个类型和该类型的对象,它可以根据类型是否为整数做出决定,同时能够访问实际对象。我试过这个

template <typename T, T &N>
struct C {
    enum { Value = 0 };
};

template <int &N>
struct C<int, N> {
    enum { Value = N };
};

但它不起作用。有什么方法可以实现类似的东西吗?

修改

我试图实现的是这样的,这将在编译时发生:

if (type is int) {
    return IntWrapper<int_value>
else {
    return type
}

您实际上可以在模板实例化中传递指向对象或引用,如下所示:

struct X {
    static const int Value = 5;
};

template <X *x>
struct C {
    static const int Value = (*x).Value; 
};

X x;

std::cout << C<&x>::Value << std::endl; // prints 5

但显然所有这一切都是通过推断x的类型来初始化模板,而x也需要全局声明。对我正在尝试做的事情毫无用处,我认为这在编译时是不可能的。

11 个答案:

答案 0 :(得分:7)

您尝试做的是无效的C ++模板。您不能将任意对象用作模板参数,您可以使用的只是类型,整数文字以及某些特殊情况下的字符串文字。

答案 1 :(得分:5)

除非我误解你,否则你想要的是不可能的。在您的示例中,您显示无效使用指针模板参数。

template <X *x>
struct C {
    static const int Value = (*x).Value; 
};

这是无效的,因为(*x).Value必须是一个常量表达式才能初始化Value。当用作Value时,确定XX::Value可以作为常量表达式使用。但这一次,它不是因为它涉及一个指针(引用在常量表达式中同样无效)。

总而言之,你不能这样做:

Magic<T, someT>::type

如果T不是int,则期望::type为T,否则IntWrapper<someT>T,因为{{1}}只能是枚举,整数,指针或引用类型。在后两种情况下,您将无法获得指针所指向的任何内容的“值”或编译时引用所引用的内容。 如果你对此感到满意,很容易解决你的问题,我不会告诉你如何(我怀疑你已经知道如何)。

我认为你已经把自己逼到一种情况,在这种情况下,解决你的问题已经无法按照给定的规则来做。当事情仍然允许解决问题时,请回过头来向我们展示您正试图解决的真正的问题。

答案 2 :(得分:4)

也许一个简单的重载模板方法适用于您的情况?

template<typename T>
void doSomething(const T& x)
{
    // ...
}
void doSomething(int x)
{
    // ...
}

答案 3 :(得分:3)


template <typename T> struct A
{
    enum { Value = false };
};
template <> struct A<int>
{
    enum { Value = true };
};

那么:


template <typename T> struct A
{
    T value_;
    A() : value() {}
    enum { is_int = false };
};
template <> struct A<int>
{
    int value_;
    explicit A( int v ) : value_( v ) {}
    enum { is_int = true };
};

答案 4 :(得分:3)

除了其他帖子:您无需再使用enum {} - 黑客攻击:

template<typename T, int val>
struct Test {
    static const int Value = 0;
};

template <int val>
struct Test<int, val> {
    static const int Value = val;
};


int main(int argc,char *argv[]) {
    const int v = Test<int,1>::Value;
}

答案 5 :(得分:2)

你可以这样做:

template<typename T, int val>
struct Test
{
    enum {Value = 0};
};

template <int val>
struct Test<int, val>
{
    enum {Value = val};
};




int main(int argc,char *argv[])
{
    int v = Test<int,1>::Value;
}  

答案 6 :(得分:2)

  

我需要一个C ++模板,给出一个   它的类型和对象   可以根据是否做出决定   类型是否为整数,而   能够访问实际的   对象。

您可以根据类型是否为整数做出决策,问题是无法使用任何类型的对象声明模板。所以关于如何决定一个类型是一个整数的问题是没有意义的。

请注意,在所有答案中,您的原始模板已整齐地更改为

template < typename T, int >
class C {};

代替你的

template< typename T, T >
class C {};

但是虽然C<int, 5>是一个完全有效的声明,但对于任意类型T都不是这种情况,点C<float, 5.>中的情况会给编译器错误。

你能发布你想要达到的目标吗?

并且对于记录,如果第二个模板参数始终是int,并且您只想在类型为整数类型时获取其值,并且其他为0,则可以执行以下操作:

#include <limits>

template< typename T, int N >
class C {
    static const int Value = (std::numeric_limits<T>::is_integer) ? N : 0;
};

答案 7 :(得分:0)

简单修复代码 - 松开引用:

template <typename T, T N>
struct C {
    enum { Value = 0 };
};

template <int N>
struct C<int, N> {
    enum { Value = N };
};

在模板参数中使用引用无论如何都没有意义,因为你实际上并没有将参数传递到任何地方。

答案 8 :(得分:0)

查看Alexandrescu的Modern C++ Design。我相信第2章有一个正确的例子,说明你想做什么。

答案 9 :(得分:0)

Template specialization可以像这样实现(代码取自www.cplusplus.com):

// template specialization
#include <iostream>
using namespace std;

// class template:
template <class T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase () {return ++element;}
};

// class template specialization:
template <>
class mycontainer <char> {
    char element;
  public:
    mycontainer (char arg) {element=arg;}
    char uppercase ()
    {
      if ((element>='a')&&(element<='z'))
      element+='A'-'a';
      return element;
    }
};

int main () {
  mycontainer<int> myint (7);
  mycontainer<char> mychar ('j');
  cout << myint.increase() << endl;
  cout << mychar.uppercase() << endl;
  return 0;
}

在您的情况下,您必须在类模板专门化中根据需要替换char。现在,我不确定你想要完成什么,但我希望上面的例子能够很好地指导你如何进行模板专业化。

答案 10 :(得分:0)

  

我试图实现的是这样的,这将在编译时发生:

if (type is int) {
    return IntWrapper<int_value>
else {
    return type
}

我不确定你为什么不开始使用IntWrapper。需要将编译时整数常量包装到IntWrapper中,如果它是int?

否则,您会尝试使用仅在运行时可用的数据来实例化模板。