我想编写make_unique
的版本,如果编译的话,将使用{ ... }
构建类型,或者(...)
。
我有一次尝试
template<typename T, typename... Args>
auto make_unique(Args&&... args) -> decltype(new T {std::forward<Args>(args)...}, std::unique_ptr<T>{}) {
return std::unique_ptr<T>(new T { std::forward<Args>(args)... });
}
这已经为SFINAE做好了准备,因为如果new T { ... }
语法不起作用,它会有替换失败,但如果new T(...)
语法有效,我不知道如何使它无法替换,而且我也不知道如何制作另一个,以便在new T { ... }
语法 工作时无法替换,并且当它不成功时编译成功,因此它可以使用new T(...)
语法。
答案 0 :(得分:3)
您可以使用调度技术通过排名转换来选择重载:
#include <memory>
#include <iostream>
template<typename T, typename... Args>
auto make_unique_impl(int, Args&&... args)
-> decltype(new T {std::forward<Args>(args)...}, std::unique_ptr<T>{}) {
std::cout << "{..} variant" << std::endl;
return std::unique_ptr<T>(new T { std::forward<Args>(args)... });
}
template<typename T, typename... Args>
auto make_unique_impl(short, Args&&... args)
-> decltype(new T (std::forward<Args>(args)...), std::unique_ptr<T>{}) {
std::cout << "(..) variant" << std::endl;
return std::unique_ptr<T>(new T ( std::forward<Args>(args)... ));
}
// dispatcher
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return make_unique_impl<T>(0, std::forward<Args>(args)...);
}
调度程序中的调用将更喜欢int
重载,因为0
的类型为int
。但如果替换失败,另一个过载也是可行的(通过积分转换)。
用法示例:
struct my_type
{
my_type(int, int) {}
my_type(std::initializer_list<int>) = delete;
};
struct my_other_type
{
my_other_type(int, int) {}
};
int main()
{
make_unique<my_type>(1, 2);
make_unique<my_other_type>(1, 2);
}