为什么不能自动用作模板类型参数?
Why can't auto be used as a template type parameter?
我一直在摆弄c++ 0x的auto
关键字,并尝试了以下方法:
std::unique_ptr<auto> ptr(new int(0));
我试着用g++ 4.4.5编译它,得到
error: invalid use of auto
通过肉眼判断,auto
很容易被推断为int
。
我的猜测是类型推断和模板引擎不会相互交谈。否则,模板引擎将知道用int
作为类型参数实例化模板类。
另一个猜测来自标准,I see this。
A member shall not be declared with auto, extern or register storage class.
但我认为这是auto
作为局部变量,而不是auto
用于推断类型。
我最后的猜测是编译器认为这是auto
存储类,而不是auto
类型演绎。
在标准中说明这背后有什么原因吗?
这是因为它必须在确定如何处理其参数之前确定要调用构造函数的类。如果将构造函数设置为模板,它将像其他模板函数一样工作——自动推导参数。
@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*) {}
};
现在unique_ptr<int*>
可以编译了。编译器如何知道选择unique_ptr<int>
还是unique_ptr<int*>
?如果我添加另一个专门化呢?
template<>
class unique_ptr<double>
{
public:
unique_ptr(int*) {}
};
编译器现在有三个选项可供选择,为了找到它们,它必须用每个可能的参数实例化模板。显然,这是不可行的,特别是在有多个模板参数和模板递归的情况下。
你能做的是创建一个工厂函数,它将推断的类型连接到一个模板实例:
template<typename T>
std::unique_ptr<T> make_unique(T* arg) { return arg; }
(当然,这是行不通的,因为unique_ptr
不能被复制。但这个想法是有效的,并在例如make_shared
和make_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);
};
只是想补充一下,大多数情况下已经存在解决方案:
template <typename T>
std::unique_ptr<T> unique_ptr_auto(T* ptr)
{
// fails to handle std::unique_ptr<T[]>, not deducible from pointer
return std::unique_ptr<T>(ptr);
}
auto ptr = unique_ptr_auto(new int(0));
显然有点冗长,但你明白了。这些"生成器函数"非常常见。
这个(或类似的)是在标准中提出的。建议的功能看起来像这样:
std::vector<int> GetMahVector();
std::vector<auto> var = GetMahVector();
然而,它被拒绝。为什么它被拒绝了,嗯,如果可能的话,你必须挖掘相关的标准过程文档。
- std::仅移动类型列表:不能在 VC++ 中放入 std::vector
- 类型值不能用于初始化类型实体
- 为什么在此上下文中非类型模板参数不能是自动的
- 类型的C 参数与父母和子类的类型参数不相容
- 为什么模板<类型名...>不能通过模板<模板类型名>识别为可实例化<typename>?
- 为什么模板参数不能从 std::addressof 解析<int>?
- 为什么默认参数不能依赖于非默认参数?
- 为什么基类型指针不能获取派生类对象的地址值?
- 为什么这个 const 参数不能与非类型模板参数匹配?
- 为什么模板类型参数不推断为"const"?
- 为什么 void 参数不能存在于具有多个参数的函数中?
- 为什么模板类型参数不能隐式强制转换?
- 为什么Qt信号的参数不能用typedef类型定义?
- Tm t1具有不完全类型,不能定义
- Int函数参数不能正常工作
- v_list(可变数参数)不能正确转换
- omnet++:未知参数.不能在模拟中使用模块参数
- 为什么类型推导不能按预期工作
- 在类声明中,为什么构造函数中的参数不能与私有部分中定义的变量同名?
- MSB3305:正在处理的COM引用-至少有一个参数不能被运行时封送处理程序封送