为什么不能自动用作模板类型参数?

Rus*_*ell 10 c++ templates c++11

我一直在玩C++ 0x的auto关键字,并尝试了以下内容.

std::unique_ptr<auto> ptr(new int(0));
Run Code Online (Sandbox Code Playgroud)

我尝试用g ++ 4.4.5编译它并得到了

error: invalid use of auto
Run Code Online (Sandbox Code Playgroud)

通过眼睛判断,auto可以很容易地推断出来int.

我的猜测是类型推断,模板引擎不会相互通信.否则,模板引擎将知道将模板类实例int化为类型参数.

另一个猜测来自标准,我看到了这一点.

A member shall not be declared with auto, extern or register storage class.
Run Code Online (Sandbox Code Playgroud)

但我认为这auto就像局部变量一样,而不是auto用于推断类型.

我最后的猜测是编译器认为这是一个auto存储类,而不是auto类型推导.

标准中有这样的理由吗?

das*_*ndy 10

那是因为它必须确定如何处理其参数之前确定调用构造函数的类.如果你将构造函数作为模板,那么它就像任何其他模板函数一样工作 - 自动推理参数.

  • 正确 - 类型推导不适用于模板类.通常你最终使用工厂函数作为解决方法,例如`auto ptr(make_unique(new int(0))); (3认同)

Ben*_*igt 5

@dascandy已正确识别您的代码有什么问题.我会尝试提供一些理由:

你期望编译器推断unique_ptr<int>因为参数是一个int*,并且unique_ptr<int>有一个接受的构造函数int*.暂时让我们忽略我们正在使用的事实std::unique_ptr,然后谈谈我们编写的模板类(并且可以专门化).

编译器为什么要推断unique_ptr<int>?争论不是int,是的int*.为什么不猜unique_ptr<int*>?当然这会导致编译器错误,因为unique_ptr<int*>构造函数不会接受int*.除非我添加专业化:

template<>
class unique_ptr<int*>
{
public:
    unique_ptr(int*) {}
};
Run Code Online (Sandbox Code Playgroud)

现在unique_ptr<int*>会编译.编译器应该如何知道选择哪个,unique_ptr<int>或者unique_ptr<int*>?如果我添加另一个专业化怎么办?

template<>
class unique_ptr<double>
{
public:
    unique_ptr(int*) {}
};
Run Code Online (Sandbox Code Playgroud)

编译器现在有三个选项可供选择,它必须使用每个可能的参数实例化模板才能找到它们.显然这是不可行的,特别是对于多个模板参数和模板递归.

你可以做的是制作一个工厂函数,它将推断的类型连接到一个模板实例:

template<typename T>
std::unique_ptr<T> make_unique(T* arg) { return arg; }
Run Code Online (Sandbox Code Playgroud)

(当然,这不起作用,因为unique_ptr无法复制.但这个想法是有效的,并在例如make_sharedmake_pair.中使用.)


一些极端丑陋的例子:

有人可能会认为这unique_ptr<shared_ptr<int>>是该代码的有效匹配.

或者怎么样:

template<typename T>
class unique_ptr
{
public:
    explicit unique_ptr(T* arg);
    unique_ptr(int*, enable_if<(sizeof(T) > 16)>::type* = 0);
};
Run Code Online (Sandbox Code Playgroud)