命名参数是否可用于模板模板参数

时间:2015-03-11 16:34:18

标签: c++ templates template-templates

如果我需要使用template-template参数定义模板foo函数,我通常会执行以下操作:

// Notice that the template parameter of class T is unnamed.
template <template <typename> class T> void f() { std::cout << "Yay!\n"; }

请注意,template-template参数的template参数是未命名的,但我们可以为此参数指定一个名称:

// Now the template parameter of class T is named INNER.
template <template <typename INNER> class T> void f(const INNER &inner)
{ std::cout << inner << " Yay!\n"; }

这似乎没有用,因为我无法在函数中提供INNER参数,上面的代码会产生以下错误:

  

错误:'INNER'未命名类型

令我惊讶的是typename INNER没有命名类型,在所有typename关键字出现后才能命名类型。无论如何,这很容易解决:

// Now INNER is the name of the template parameter of class T and also
// the name of the second template parameter of foo.
template <template <typename INNER> class T, typename INNER> void f(const INNER &inner)
{ std::cout << inner << " Yay!\n"; }
// ...
f<std::valarray, int>(666); // Prints "666 Yay!"

但最后,INNER参数毕竟不需要名称:

// Now the template parameter of class T is unnamed one more time,
// INNER is the name of the second template parameter of foo.
template <template <typename> class T, typename INNER> void f(const INNER &inner)
{ std::cout << inner << " Yay!\n"; }
// ...
f<std::valarray, int>(666); // Prints "666 Yay!"

并且(确定您已经在我之前注意到)模板模板参数的参数中的名称被忽略了!它确实被忽略了,因为如果不是它应该与foo的第二个模板参数进行名称冲突,不是吗?

忽略模板模板参数参数名称的另一个演示:

// Now T is the name of the template parameter of class T and also
// the name of the template parameter of foo!
template <template <typename T> class T> void f()
{ std::cout << "Yay!\n"; }
// ...
f<std::valarray>(); // prints "Yay!"

模板模板参数和模板模板本身同时使用名为T的类型?我不这么认为,模板模板参数中的名称会被忽略AFAIK。

那么,问题是什么?

  1. 我的猜测是否正确?模板模板参数的命名模板参数的名称会被忽略吗?
  2. 如果我弄错了并且我误解了整个事情,那么将命名参数用于模板模板参数?你能提供一些有用的例子吗?
  3. 对于#2上的有用示例,我指的是只能使用模板模板参数的命名模板参数实现的东西。

1 个答案:

答案 0 :(得分:9)

[basic.scope.temp] / P1:

  

a的模板参数名称的声明性区域   template template-parameter 是最小的 template-parameter-list   其中引入了名称。

(现在尝试说10次。)

可以在该列表中使用。例如,

template < template<class T, T t> class TP > class foo {};
//                           ^  ^-----T's scope ends here
//                           |
//                           T can be used here

foo<std::integral_constant> bar;