2016-04-28 16 views
3

私はいくつかのテンプレートメタプログラミングを行っています。私は、SFINAE(Substitution Failure Is Not An Error)による式の妥​​当性に応じてクローニングの方法を選択する一般的なクローニング機能を実装したいと考えています。std :: make_uniqueはSFINAEに対応していますか?

unique_ptr<T>(new T(std::forward<Args>(args)...)) 

んこの平均:それは

機能

make_unique<T>(std::forward<Args>(args)...) 

と等価であることを述べている

this reference websiteで次のコード

template <typename T> 
auto my_clone(const T & t) -> decltype(std::make_unique<T>(t)) 
{ 
    return std::make_unique<T>(t); 
} 

は、私が機能my_cloneの他のオーバーロードを持っている場合でも

template <typename T> 
auto my_clone(const T & t) -> decltype(std::unique_ptr<T>(new T(t))) 
{ 
    return std::unique_ptr<T>(new T(t)); 
} 

と完全に同等であることを?言い換えれば:std::make_unique()SFINAE-friendlyですか?

Tでない場合コピー可能な場合、後者のコードはSFINAEのために過負荷解決に参加しません。 、必見のunique_ptr<T>(new T(std::forward<Args>(args)...))を返し

template <class T, class... Args> unique_ptr<T> std::make_unique(Args&&... args); 

...:標準のみことを保証

#include <memory> 

// It does **not** work with this snippet: 
template <typename T> 
auto my_clone(const T & t) -> decltype(std::make_unique<T>(t)) 
{ 
    return std::make_unique<T>(t); 
} 

/* // But it works with this snippet instead: 
template <typename T> 
auto my_clone(const T & t) -> decltype(std::unique_ptr<T>(new T(t))) 
{ 
    return std::unique_ptr<T>(new T(t)); 
}*/ 

// This is another overload for testing purposes. 
template <typename T> 
auto my_clone(const T & t) -> decltype(t.clone()) 
{ 
    return t.clone(); 
} 

class X 
{ 
public: 
    X() = default; 

    auto clone() const 
    { 
     return std::unique_ptr<X>(new X(*this)); 
    } 

private: 
    X(const X &) = default; 
}; 

int main() 
{ 
    // The following line produces the compiler error: 
    // "call to 'my_clone' is ambiguous" 
    const auto x_ptr = my_clone(X()); 
} 
+1

標準がありませんそれを保証しないので、あなたはそれに頼るべきではありません。 – Holt

+1

@Holtスタンダードではないのは何ですか? [unique.ptr.create]に 'make_unique'が返されます。*:unique_ptr (新しいT(std :: forward (args)...))'を返します。 – NathanOliver

+1

@ NathanOliverはい、標準では 'T'が' Args && ... 'を使って構成できない場合、 'std :: make_unique(Args && ...)'が存在してはならないことを保証していません。 – Holt

答えて

6

:オンここ

はC++ 14とGCC 5.3でコンパイルに失敗した小さな例ですArgs...を使用してTがコンストラクタブルである場合にのみmake_unique関数が存在することを保証するものではないため、SFINAEは標準に準拠していないため、依存することはできません。

標準言及make_uniqueのセクションのみ:

§ 20.8.1.4 [unique.ptr.create]:

template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args); 
  1. 備考:この関数は参加しないものをTが配列でない場合は、オーバーロードの解決。
  2. 返品:unique_ptr<T>(new T(std::forward<Args>(args)...))あなたのケースでは

、あなたはstd::unique_ptr<T>(new T(...))とバージョンを使用するか、例えば、(Jarod42 @ @Yakk、)あなたのmy_clone SFINAEフレンドリーにするためにis_copy_constructibleを使用するかしたいことがあります。

template <typename T, 
      typename = std::enable_if_t<std::is_copy_constructible<T>::value>> 
auto my_clone(const T & t) -> decltype(std::make_unique<T>(t)) { 
    return std::make_unique<T>(t); 
} 
+1

そのトリプルネガが大好きです:) –

関連する問題