在C ++中使用部分专业化11

时间:2012-07-23 15:22:17

标签: c++ templates c++11

我有以下代码:

template<class T, int I=44> struct test {T j = I;};

template<int J> struct test<int, J> {int j = J;};

int main()
{
  test<55> jj;

  std::cout << jj.j << std::endl;
  return(1);
}

编译器(clang)仅抱怨行test<55> jj

我不明白为什么?有工作吗?

如果它抱怨该行,为什么它不抱怨第二个模板定义呢?

提前致谢。

消息是:

enable.cpp:17:8: error: template argument for template type parameter must be a type
test<55> jj;
   ^~
enable.cpp:9:16: note: template parameter is declared here
template<class T, int I=44> struct test

2 个答案:

答案 0 :(得分:6)

问题在于您还没有理解选择类模板专业化的方式。

您的专长:

template<int J> struct test<int, J> {int j = J;};

不会创建只需传入单个int模板参数的模板。

test<55> jj; // doesn't work because there's no template<int J> struct test

相反它的作用是创建template<class T, int I> struct test的特化,当template<class T, int I> struct test的模板参数与特化时匹配时使用,test<int,J>

test<int,55> jj; // uses the specialization template<int J> struct test<int, J>

这是标准的关键引用:

  

在引用类模板特化的类型名称中(例如,   A<int, int, 1>)参数列表应与模板参数匹配   主模板的列表。 a的模板参数   从主要模板的参数中推断出专业化。 [强调添加]

     

- 14.5.5.1 [temp.class.spec.match] p4


您似乎尝试将int设置为T的默认类型,同时为I设置独立的默认值。我认为您的意图是能够指定类型和值,仅指定类型并将44作为默认值,或者仅指定值并将int作为默认类型。

不幸的是,我不知道如何指定这样的独立默认值。您可以指定默认值(template<class T=int, int I=44> struct test),但获取默认值也需要接受默认值。

但是,如果你愿意使用第二个名字,那么你可以这样做:

template <int I>
using test_int = test<int, I>;

这会创建一个模板别名,您只需指定一个值:

test_int<55> jj;

这将最终使用任何特殊化test<int, I>来解决是否存在显式特化或编译器是否生成隐式特化。

答案 1 :(得分:3)

发生第一个错误是因为编译器尝试使用55实例化第一个模板参数(class T)。这不起作用,因为55本身不是一个类型,而是一个实例化它的。但是,test<int>有效,因为此处模板参数是模板签名所要求的类型。

你想要的是“currying”类型,又名。模板别名:

template <typename T>
struct test2 = using test<T, 55>;

在这里,您只需提供一个T来选择55作为固定的第二个参数。但您仍然需要使用该类型,具体为T,例如test2<double>

评论表明您也可能对以下变体感兴趣:

template <int I>
using test3 = test<int, I>;

在这里,您将第一个类型参数修复为int,这允许您像在代码中一样使用它:

test3<55> t;