ixS*_*Sci 10 c++ language-lawyer
假设我们有以下代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
由于第一个dummyMe参数是rvalue-reference ,因此无法编译.有人可以在Standardese中解释为什么模板模板参数与转发参考不相符,为什么它用简单的英语.
PS我偶然发现了这个和那些问题,但我没有在答案中看到任何真实的证据.
上面链接的答案和这个问题的答案断言Container<T>不能算作模板参数.我认为没有理由这样做.让我们的例子更简单:
template <template <typename=int> class Container>
void dummyMe(Container<>&&)
{};
Run Code Online (Sandbox Code Playgroud)
现在我们有一个几乎与以下相同的示例:
template <typename Container>
void dummyMe(Container&&)
{};
Run Code Online (Sandbox Code Playgroud)
但是以完全不同的方式对待它.为什么?为什么Container<>&&不能被视为同样的事情template <typename=int> class Container作为Container&&对typename Container?
Sto*_*ica 11
术语"转发参考"在[temp.deduct.call/3](来自C++ 17 draft n4659)中描述:
转发引用是对cv-unqualified 模板参数的rvalue引用,该 参数不表示类模板的模板参数(在类模板参数推导期间).
在你的例子Container<T>不是一个模板参数,它是你从模板参数由类型T和Container.为了使引用真正转发,您只能使用T&&.虽然Conatiner是模板参数,但您不能引用模板(上面的段落甚至明确提到它).该类型 Container<T>是不一样的模板 Container.这是一个实例化的类.1
虽然您可以使用SFINAE获取只能绑定到容器类型的转发引用,但我个人觉得您最好只是重载该功能.
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&&)
{}
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&)
{}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
从这些生产规则中可以清楚地看出,dummyMe它只有两个模板参数:typename T和template <typename> class Container.命名每个参数的标识符是T和Container.T命名第一个参数并Container命名第二个参数.Container<T>不是标识符,也不是两者的名称.