2016-04-12 5 views
1

私はコンストラクタを持たないクラスから派生しようとしています。intからですが、nullptrから、1つの引数を取るときにできるだけジェネリックとしてコンストラクタを作成しようとしています。SFINAEがnullptrのオーバーロードで動作しないのはなぜですか?

#include <cstddef> 
#include <iostream> 

struct Base 
{ 
    Base(std::nullptr_t){} 
    Base(){} 
    // some other constructors, but not from int 
}; 

struct Test : Base 
{ 
    Test(std::nullptr_t) : Base(nullptr) 
    { 
     std::cerr << "Test(nullptr)\n"; 
    } 
    template<typename T> 
    Test(T v) : Base(v) {} 
}; 

int main() 
{ 
    Base b=0;  // works 
    Test z=nullptr; // works 
    Test t=0;  // compilation error 
} 

なぜそれが起こるん。しかし、いくつかの理由のために正しいコンストラクタは失敗でテンプレートコンストラクタの結果にintの置換があっても、取られるとは思われませんか? SFINAEが意味するものではありませんか?そして、私はこの問題をどのように修正できますか?

+1

SFINAE-effect –

+2

の場合、 'template 'を使用してください。 –

+1

短いストーリー: '0'は' nullptr'になるための変換が必要なので、テンプレートが優先されます。 – Quentin

答えて

2

メンバ初期化リストは、ソートされた「即時コンテキスト」の一部ではありません。 SFINAEは、この直接的なコンテキストだけを保護します。

これに加えて、SFINAEは関数本体(定義部分)に属していない関数宣言部分への置換を守ります。メンバー初期化リストは、コンストラクタ本体に属します。この本体は宣言から独立してインスタンス化され、ここのエラーは致命的です。

0

GCCは、これは

  • Test t=0;T==intと、テンプレートTest(T)を経由して行くことを示して

    36576202.cpp: In instantiation of ‘Test::Test(T) [with T = int]’: 
    36576202.cpp:25:12: required from here 
    36576202.cpp:18:23: error: no matching function for call to ‘Base::Base(int&)’ 
        Test(T v) : Base(v) {} 
            ^
    36576202.cpp:18:23: note: candidates are: 
    36576202.cpp:7:5: note: Base::Base() 
        Base(){} 
        ^
    36576202.cpp:7:5: note: candidate expects 0 arguments, 1 provided 
    36576202.cpp:6:5: note: Base::Base(std::nullptr_t) 
        Base(std::nullptr_t){} 
        ^
    36576202.cpp:6:5: note: no known conversion for argument 1 from ‘int’ to ‘std::nullptr_t’ 
    36576202.cpp:4:8: note: constexpr Base::Base(const Base&) 
    struct Base 
         ^
    36576202.cpp:4:8: note: no known conversion for argument 1 from ‘int’ to ‘const Base&’ 
    36576202.cpp:4:8: note: constexpr Base::Base(Base&&) 
    36576202.cpp:4:8: note: no known conversion for argument 1 from ‘int’ to ‘Base&&’ 
    

    私に語りました。これは有効な代替語ですので、SFINAEは意味がありません。

  • ​​この場合、存在しないBase(int)が必要です。そして、intからnullptr_tへの変換はありません。
関連する問題