为什么不能将std :: unique_ptr用作“ template <class> class”自变量?

时间:2018-07-16 08:35:45

标签: c++ c++11 unique-ptr template-deduction template-templates

此代码:

#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>

3 个答案:

答案 0 :(得分:6)

因为模板模板参数需要完全匹配。这意味着默认模板参数在这里不相关。请注意,将模板模板参数扩展为两个模板参数只会偶然地起作用:允许实现添加比标准定义更多的模板参数,并且在SFINAE围绕标准容器的情况下经常可以这样做。

这也是我通常建议不要使用任何模板模板参数,而仅使用普通模板类型名的主要原因。如果您需要访问嵌套模板类型,请提供内部访问器,例如value_type或外部访问器(例如tuple_element)可在模板内部访问这些访问器。


注意:这显然已在C ++ 17中发生了变化,在此情况下,匹配不再精确,但稍稍放松却更加复杂。尽管如此,我还是建议不要一般使用模板模板参数。

答案 1 :(得分:4)

std::unique_ptr有另一个默认的模板参数,因此template <typename> class Ptrstd::unique_ptr不匹配

template <typename...> class Ptr将起作用

cppreference

答案 2 :(得分:1)

正如@HolyBlackCat所建议的,我们不再需要对C ++ 17使用任何解决方法-以及OP的代码does indeed compile(coliru.com)。

GCC 6.3.0默认情况下会编译C ++ 14代码,并且不会应用此语言语义更改。