1

if that compiles または else で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(...)わかりませんし、もう一方を作る方法もわかりません。 1つは、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オーバーロードを優先します。ただし、置換が失敗した場合は、他のオーバーロードも (整数変換を介して) 実行可能です。0int

使用例:

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 に答える