سؤال

I am wanting to write a version of make_unique that will construct the type with { ... } if that compiles, or else (...).

I have an attempt

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)... });
}

This is ready for SFINAE because it will have a substitution failure if the new T { ... } syntax doesn't work, but I don't know how to make it fail to substitute if the new T(...) syntax works, and also I don't know how to make the other one so that it fails to substitute when the new T { ... } syntax does work and compile successfully when it doesn't so it can use the new T(...) syntax.

هل كانت مفيدة؟

المحلول

You could select an overload by ranking of conversions, using a dispatching technique:

#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)...);
}

The call in the dispatcher will prefer the int overload, since 0 is of type int. But if substitution fails, the other overload is also viable (via an integral conversion).

Usage example:

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);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top