2017-12-22 34 views
4
#include <iostream> 

using namespace std; 

template <typename T> 
class test { 
public: 
    T value; 

    template <typename... Args, typename = decltype(T())> 
    test(Args... args): value(args...) 
    { 
     cout <<"ctor running\n"; 
    } 

    template <typename... Args> 
    test(Args...) : value(1) 
    { 
     cout <<"ctor unspec running\n"; 
    } 
}; 


class t 
{ 
public: 
    t() = delete; 
    explicit t(int) {} 
}; 


int main() 
{ 
    test<t> h; 
} 

私が作成したオブジェクト(h)のための第二constructorを呼び出すようにしようとしています。私はこのエラーを取得する理由を知りません。私は全体class tprivateを作ってみましたが、それはどちらかそれを修正しませんでしたC++コンストラクタSFINAE

prog.cc: In function 'int main()': 
prog.cc:45:13: error: call of overloaded 'test()' is ambiguous 
    test<t> h; 
      ^
prog.cc:25:5: note: candidate: 'test<T>::test(Args ...) [with Args = {}; T = t]' 
    test(Args... args) 
    ^~~~ 
prog.cc:19:5: note: candidate: 'test<T>::test(Args ...) [with Args = {}; <template-parameter-2-2> = t; T = t]' 
    test(Args... args): value(args...) 
    ^~~~ 

。私は

"ctor unspec running"

`すなわち、印刷を実行するための第二 constructorをしたい、私はここで何をしないのですか?最初の constructorコールは SFINAed離れている必要があります。 tdefault constructedになることはできませんが、 ambiguousコールエラーが発生するため、 typename = decltype(T())は動作しません。

答えて

4

SFINAEは即時コンテキストでのみ発生します。 Tはクラスのテンプレート引数であり、関数のテンプレート引数ではないため、直後のコンテキストではありません。つまり、「難しい」エラーになります。コンストラクタのテンプレート引数にどの引数を渡しても、それは常にエラーになるので、これは難しいエラーです。

ソリューションはTに等しいテンプレート引数を追加し、SFINAEを作るためにそれを使用することです:

template <typename... Args, typename U = T, typename = decltype(U{})> 
test(Args... args): value(args...) 
{ 
    cout <<"ctor running\n"; 
} 

Uが即時コンテキストであるので、SFINAEがここで適用されます。

SFINAEでは、注文は行われません。すべてのマッチング関数は「等価」であり、複数のマッチング関数がある場合、制約があるため「良好」なものは存在しません。だから、逆制約と他のものを制限するために良いでしょう:

template <typename... Args, typename U = T, 
    std::enable_if_t<!std::is_default_constructible<U>::value>* = nullptr> 
test(Args...) : value(1) 
{ 
    cout <<"ctor unspec running\n"; 
} 

Live example

+0

は答えてくれてありがとう。受け入れられました。 – PYA

関連する問題