2016-09-07 11 views
4

TUから構築可能であるならば、私は、T周りのラッパーオブジェクトの構築を可能にする次のような手法に遭遇したが、タイプUのオブジェクトからきた:SFINAE条件とコンストラクタ引数の型

template< typename T > 
struct S { 
    template< typename U, 
       typename = std::enable_if_t< 
        std::is_constructible< T, U >::value > > 
    explicit S (U&& arg) : value (arg) 
     { } 
    ... 
}; 

IIUC、 is_constructible試験で使用されるタイプUargのCV修飾型とは異なることができます。
は、それが表現value(arg)が有効であるものの、SFINAEテストが失敗する可能性があることは可能ですか?

答えて

4

表現値(arg)は有効ですが、SFINAEテストに失敗する可能性はありますか?

あなたが書いた方法S:はい、可能です。
それは最小限、(ない)作業例は以下:

, typename = std::enable_if_t<std::is_constructible< T, U >::value > 

問題がある:あなたが次の行をコメントアウトした場合にコンパイルされませんが、それはコンパイルん上記のコード

#include<type_traits> 

template< typename T > 
struct S { 
    template< typename U 
       , typename = std::enable_if_t<std::is_constructible< T, U >::value > 
    > explicit S (U&& arg) : value{arg} {} 

    T value; 
}; 

struct A {}; 
struct B { 
    B(A &) {} 
}; 

int main() { 
    S<B> s(A{}); 
} 

をコンストラクタパラメータを転送していないことを確認します。代わりに、あなたはvalueの引数として(つまりargある)Aに型右辺値参照の変数への左辺値参照を使用しています。
B右辺値参照からAに構築可能ではないとsfinae式が失敗した(正確に)、しかし、あなたは実際にそれが動作するsfinae表現を削除し、パラメータを構築するために、このような参照を使用していません。実際に
は、Bあなたがvalue{arg}を書くときに使用しているものであるAへの左辺値参照、から構成可能です。


それは次のようにあなたは、むしろSを書く必要があります。

#include<utility> 

// ... 

template< typename T > 
struct S { 
    template< typename U 
       , typename = std::enable_if_t<std::is_constructible< T, U >::value > 
    > explicit S (U&& arg) : value (std::forward<U>(arg)) { } 

    T value; 
}; 

は、実際には右のタイプのパラメータを転送するstd::forwardの使用に注意してください。
これは、少なくとも上記の問題を解決し、それはあなたが探していた保証を与える必要があります。

関連する問題