2015-12-08 8 views
13

テンプレートクラスのメンバ関数のオーバーロードを解決する際、g ++(5.2.1-23)とclang(3.8.0) )、-std=c++14enable_ifでのC++テンプレートのオーバーロード:g ++とclangとの動作が異なる

#include <iostream> 
#include <type_traits> 

struct Base 
{ 
    template <typename T> 
    auto a(T t) -> void { 
    std::cout<< "False\n"; 
    } 
}; 

template <bool Bool> 
struct Derived : public Base 
{ 

    using Base::a; 
    template <typename T, bool B = Bool> 
    auto a(T t) -> std::enable_if_t<B, void> 
    { 
    std::cout<< "True\n"; 
    } 
}; 

int main() 
{ 
    Derived<true> d; 
    d.a(1); // fails with g++, prints "true" with clang 
    Derived<false> d2; 
    d2.a(1); // fails with clang++, prints "false" with g++ 
} 

Derived<true>::aへの呼び出しは次のようなメッセージを持つG ++で失敗します。

test.cc: In function ‘int main()’: 
test.cc:28:8: error: call of overloaded ‘a(int)’ is ambiguous 
    d.a(1); 
     ^
test.cc:18:8: note: candidate: std::enable_if_t<B, void> Derived<Bool>::a(T) [with T = int; bool B = true; bool Bool = true; std::enable_if_t<B, void> = void] 
    auto a(T t) -> std::enable_if_t<B, void> 
     ^
test.cc:7:8: note: candidate: void Base::a(T) [with T = int] 
    auto a(T t) -> void { 
     ^

Derived<false>::aへの呼び出しは次のようなメッセージと打ち鳴らす++で失敗します。

test.cc:32:6: error: no matching member function for call to 'a' 
    d2.a(1); 
    ~~~^ 
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/type_traits:2388:44: note: candidate template ignored: disabled by 'enable_if' [with T = int, B = false] 
    using enable_if_t = typename enable_if<_Cond, _Tp>::type; 
             ^

私の推測では、ということですそれらはusing Base::a;と異なって解釈され、clangでは考慮されませんが、g ++では(多分あまりにも)考慮されます。私は、Derivedtrueがパラメータとしてある場合、a()の呼び出しがの実装に送出され、一方、パラメータがfalseの場合、呼び出しはBase::aにディスパッチされることが考えられます。

どちらも間違っていますか?誰が正しい?誰にバグレポートを提出すればよいですか?誰かが何が起こっているか説明できますか? 3.3.10/P3名と

おかげ

答えて

3

は[basic.scope.hiding]隠蔽:メンバ関数定義で

、ブロック スコープで名前の宣言は宣言を隠し同じクラスのメンバー の名前; 3.3.7を参照してください。 派生クラス (第10項)のメンバーの宣言は、同じ名前の の基本クラスのメンバーの宣言を隠します。 10.2

また

7.3.3/P15使用宣言[namespace.udecl]参照:using宣言派生 クラススコープに基本クラスから名前をもたらし

、メンバ関数 派生クラスのメンバ関数テンプレートは、メンバ関数をオーバーライドまたは非表示にします。同じ名前、パラメータタイプリスト(8.3.5)、 cv-qualification、およびref-qualifier(存在する場合)を持つメンバテンプレート ファンクションテンプレート(むしろ よりも矛盾しています)。 [注: コンストラクタの名前を使用する宣言については、12.9を参照してください。 - エンドノート] [例:

​​

- エンド例]

これは、メンバー名のルックアップ中に解決されます。したがって、テンプレート引数の控除の前です。その結果、コメントの中で述べられているように、TCのテンプレート機能はSFINAEの評決に関係なく隠されています。

したがって、CLANGは正しく、GCCが間違っています。

+2

これは隠されていて、オーバーロードセットに含まれていないか、または表示されており、オーバーロードセットの一部です。 「時には隠されている」というのは意味をなさない。 –

+1

だから私が正しく理解していれば、g ++は間違っているのです。なぜなら、 'using'との競合は考慮されるべきではなく、clangは間違っているからです。何も見つからなければ、' using'を見なければなりません。だから私は両方のコンパイラでバグレポートを提出する必要があります。 –

+0

@VTolmer標準的な言い回しに基づいて、私はこれが当てはまると信じています。 – 101010

関連する問題