此代码:
#include <memory>
template <template <typename> class Ptr>
class A { Ptr<int> ints; };
using B = A<std::unique_ptr>;
产生以下错误(使用GCC 6.3):
a.cpp:6:28: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class> class Ptr> class A’
using B = A<std::unique_ptr>;
^
a.cpp:6:28: note: expected a template of type ‘template<class> class Ptr’, got ‘template<class _Tp, class _Dp> class std::unique_ptr’
现在,我可以解决此问题,就像这样:
template <typename T>
using plugged_unique_ptr = std::unique_ptr<T>;
using B = A<plugged_unique_ptr>;
但是我为什么必须这么做?我的意思是,为什么编译器不愿意将std::unique_ptr
的第二个模板参数“插入”其默认值,并允许std::unique_ptr
用作A
的模板参数? / p>
答案 0 :(得分:6)
因为模板模板参数需要完全匹配。这意味着默认模板参数在这里不相关。请注意,将模板模板参数扩展为两个模板参数只会偶然地起作用:允许实现添加比标准定义更多的模板参数,并且在SFINAE围绕标准容器的情况下经常可以这样做。
这也是我通常建议不要使用任何模板模板参数,而仅使用普通模板类型名的主要原因。如果您需要访问嵌套模板类型,请提供内部访问器,例如value_type
或外部访问器(例如tuple_element
)可在模板内部访问这些访问器。
注意:这显然已在C ++ 17中发生了变化,在此情况下,匹配不再精确,但稍稍放松却更加复杂。尽管如此,我还是建议不要一般使用模板模板参数。
答案 1 :(得分:4)
std::unique_ptr
有另一个默认的模板参数,因此template <typename> class Ptr
与std::unique_ptr
不匹配
template <typename...> class Ptr
将起作用
答案 2 :(得分:1)
正如@HolyBlackCat所建议的,我们不再需要对C ++ 17使用任何解决方法-以及OP的代码does indeed compile(coliru.com)。
GCC 6.3.0默认情况下会编译C ++ 14代码,并且不会应用此语言语义更改。