模板模板参数和转发引用
template template parameters and forwarding references
假设我们有以下代码:
template<typename T>
class C
{};
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&&)
{};
int main(int argc, char* argv[])
{
C<int> c;
dummyMe(c);
return 0;
}
由于第一个dummyMe
参数是右值引用,因此无法编译。有人可以用标准语言解释我为什么模板模板参数与转发引用不相处,为什么用简单的英语如此。
附言我偶然发现了这个问题和那个问题,但我在答案中没有看到任何真正的证据。
上面链接中的答案和此问题的答案断言Container<T>
不能计为模板参数。我看不出为什么会这样。让我们使示例更简单:
template <template <typename=int> class Container>
void dummyMe(Container<>&&)
{};
现在我们有一个几乎与以下内容相同的示例:
template <typename Container>
void dummyMe(Container&&)
{};
但这是以完全不同的方式对待的。为什么?为什么Container<>&&
不能被视为template <typename=int> class Container
和Container&&
typename Container
一回事?
术语"转发参考"在[temp.deduct.call/3](来自C++17草案n4659(中描述:
转发引用是对 cv 不合格的右值引用 不表示 的模板参数的模板参数类模板(在类模板参数推导期间(。
在您的示例中,Container<T>
不是模板参数,而是您从模板参数T
和Container
组成的类型。为了使引用真正转发,您只能使用T&&
。虽然Conatiner
是模板参数,但不能引用模板(上面的段落甚至明确提到了它(。Container<T>
的类型与模板Container
不同。这是一个实例化的类。
虽然您可以使用 SFINAE 获取只能绑定到容器类型的转发引用,但我个人认为您最好重载该函数。
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&&)
{}
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&)
{}
1[temp.spec/2] - 从类模板实例化的类称为实例化类
链接的答案和这个问题的答案断言
Container<T>
不能算作模板参数
什么是或不是模板参数不需要太多解释。[temp.param]
中明确定义:
template-parameter:
type-parameter
parameter-declaration
type-parameter:
type-parameter-key ...(opt) identier (opt)
type-parameter-key identier(opt) = type-id
template < template-parameter-list > type-parameter-key ...(opt) identier(opt)
template < template-parameter-list > type-parameter-key identier(opt) = id-expression
type-parameter-key:
class
typename
从这些生产规则中可以清楚地看出,dummyMe
正好有两个模板参数:typename T
和template <typename> class Container
。命名每个参数的标识符T
和Container
。T
命名第一个参数,Container
命名第二个参数。Container<T>
不是标识符,并且不命名两者。
- 正在折叠转发引用
- 如何在模板中转发右值和左值引用
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- C++ 何时使用常量引用而不是转发引用
- 为什么转发声明的好友类不能在类中引用?
- C++完美转发:如何避免悬空引用
- C++:通用(转发)引用中不允许常量
- 模板模板参数和转发引用
- 常量转发引用给出错误 C2440:"正在初始化":无法从"常量标准::字符串"转换为"常量标准::字符串 &&"
- 具有右值引用,而不是使用可变参数模板转发引用
- 自定义类型转换运算符在转发引用上调用时不起作用(当对象按值传递时有效)
- 如何从常量引用或通过转发模板临时构造对象
- 结构化绑定和转发引用是否混合良好?
- 如何声明接受转发引用并返回引用或副本的函数模板
- 间接转发引用
- 为什么调用转发引用构造函数而不是复制构造函数?
- 为什么 std::get 没有一个接受转发引用的签名
- 有没有办法在不引用其模板类型的情况下转发声明指向类的指针
- c++重新评估引用转发性能
- 右值引用转发错误