1

我想写一个版本,如果可以编译,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(...)语法。

4

1 回答 1

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);
}
于 2013-10-20T02:57:13.860 回答