unique_ptr 和 make_unique 中的自动模板参数推导
Automatic template parameter deduction in unique_ptr and make_unique
为什么直接调用class构造函数会得到模板自动推导,而std::unique_ptr
和std::make_unique
却没有得到?这是一个例子:
#include <memory>
template <class T>
class C
{
public:
C(const T * const t_) : t(t_) {}
~C(void) { delete t; }
private:
const T * const t;
};
示例 1(有效):
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
return 0;
}
示例 2(不编译):
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
std::unique_ptr p(c); // class template argument deduction failed
return 0;
}
示例 3(有效):
int main(void)
{
const int * const t = new int;
const auto c = std::make_unique<C<int>>(t);
return 0;
}
示例 4(不编译):
int main(void)
{
const int * const t = new int;
// no matching function for call to ‘make_unique<template<class T> class C>(const int* const&)
const auto c = std::make_unique<C>(t);
return 0;
}
代码是用 g++ -std=c++17
(gcc-11.2.0) 编译的。
例子2和例子4有什么问题?如何修复它们?
非常感谢您的帮助!
在 #2 中,CTAD 被故意 禁用 std::unique_ptr
以避免 std::unique_ptr(new T[10])
的问题,它看起来就像 std::unique_ptr(new T)
但需要 delete[]
而不是 delete
.
在#4 中,语言 根本不支持这个:无法传递 any class 模板作为模板参数,以便根据 std::make_unique
中的函数参数执行 CTAD。 (可以传递具有特定(元)签名的 class 模板,但这不适合一般设施。)
这是解决问题的一种方法:
template <class T>
auto MakeUnique(T t)
{ return std::unique_ptr<std::remove_reference_t<decltype(*t)>>(t); }
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
auto p = MakeUnique(c);
return 0;
}
为什么直接调用class构造函数会得到模板自动推导,而std::unique_ptr
和std::make_unique
却没有得到?这是一个例子:
#include <memory>
template <class T>
class C
{
public:
C(const T * const t_) : t(t_) {}
~C(void) { delete t; }
private:
const T * const t;
};
示例 1(有效):
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
return 0;
}
示例 2(不编译):
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
std::unique_ptr p(c); // class template argument deduction failed
return 0;
}
示例 3(有效):
int main(void)
{
const int * const t = new int;
const auto c = std::make_unique<C<int>>(t);
return 0;
}
示例 4(不编译):
int main(void)
{
const int * const t = new int;
// no matching function for call to ‘make_unique<template<class T> class C>(const int* const&)
const auto c = std::make_unique<C>(t);
return 0;
}
代码是用 g++ -std=c++17
(gcc-11.2.0) 编译的。
例子2和例子4有什么问题?如何修复它们?
非常感谢您的帮助!
在 #2 中,CTAD 被故意 禁用 std::unique_ptr
以避免 std::unique_ptr(new T[10])
的问题,它看起来就像 std::unique_ptr(new T)
但需要 delete[]
而不是 delete
.
在#4 中,语言 根本不支持这个:无法传递 any class 模板作为模板参数,以便根据 std::make_unique
中的函数参数执行 CTAD。 (可以传递具有特定(元)签名的 class 模板,但这不适合一般设施。)
这是解决问题的一种方法:
template <class T>
auto MakeUnique(T t)
{ return std::unique_ptr<std::remove_reference_t<decltype(*t)>>(t); }
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
auto p = MakeUnique(c);
return 0;
}