有时候我看到过这样的代码:
void* Create()
{
int* t{new int{10}};
return t;
}
class Deleter
{
//uncomment in order to compile
//using pointer = void*;
public:
void operator()(void* t)
{
delete t;
}
};
unique_ptr<int, Deleter> ptr{Create()};
它没有编译。对于VS2013,它说:
错误:C2440:'初始化':无法从'initializer-list'转换 'std :: unique_ptr'没有构造函数可以获取源代码 类型或构造函数重载解析是不明确的
但是如果我取消注释行using pointer = void*;
它就可以了!此外,如果我将别名更改为不同于pointer
的名称,我会得到相同的错误。因此,使用具有确切名称using
的{{1}}指令似乎至关重要。但为什么?我找不到任何解释。
答案 0 :(得分:7)
您的unique_ptr
与T=int
一起宣布。但是,constructors in std::unique_ptr
不是T*
,而是pointer
参数。
此pointer
类型定义为
std::remove_reference<Deleter>::type::pointer if that type exists, otherwise T*
当您未提供Deleter::pointer
时,它最终为int*
,当然无法从void*
(来自Create
)初始化。
答案 1 :(得分:2)
[C++11: 20.7.1.2/3]
如果类型remove_reference<D>::type::pointer
存在,则unique_ptr<T, D>::pointer
应为remove_reference<D>::type::pointer
的同义词。否则unique_ptr<T, D>::pointer
应为T*
的同义词。类型unique_ptr<T, D>::pointer
应满足 NullablePointer (17.6.3.3)的要求。
这是必需的,因为你没有operator()(int*)
- 你正在“黑客攻击”,允许使用operator()(void*)
代替删除器假装它是void*
的删除者。 / p>
你的删除器整体是否仍然严格有效,即使它是编译的,我也不想说。