2017-07-12 2 views
12

私は、Microsoft C++コンパイラ14.1(Visual Studio 2017)でライブラリをコンパイルしようとしていますが、クラスメソッドへのあいまいな呼び出しのために奇妙なエラーが発生しています。なぜこのC++コードは、Microsoftコンパイラでのみあいまいなメソッド呼び出しですか?

1> C:\ Users \ユーザーのPMAのドキュメントは、Visual Studioを\ \

2017\projects\consoleapplication3\consoleapplication3\consoleapplication3.cpp(87): error C2668: 'DerivedState::onEvent': ambiguous call to overloaded function 
1>c:\users\pmas\documents\visual studio 2017\projects\consoleapplication3\consoleapplication3\consoleapplication3.cpp(59): note: could be 'void DerivedState::onEvent<Context>(Fsm &,const Event &)' 
1>  with 
1>  [ 
1>   Fsm=Context 
1>  ] 
1>c:\users\pmas\documents\visual studio 2017\projects\consoleapplication3\consoleapplication3\consoleapplication3.cpp(45): note: or  'void State<DerivedState>::onEvent<Context>(Fsm &,const Event &)' 
1>  with 
1>  [ 
1>   Fsm=Context 
1>  ] 
1>c:\users\pmas\documents\visual studio 2017\projects\consoleapplication3\consoleapplication3\consoleapplication3.cpp(87): note: while trying to match the argument list '(Context, Event)' 

コード、私は次の出力を得る

#include <iostream> 

struct Event 
{}; 

template<typename Derived> 
struct State 
{ 
public: 
    template<typename Fsm> 
    void onEvent(Fsm& fsm, const Event& event) 
    { 
     std::cout << "State::onEvent\n"; 
    } 

}; 

struct DerivedState 
    : State<DerivedState> 
{ 
public: 
    using State::onEvent; 

    template<typename Fsm> 
    void onEvent(Fsm& fsm, const Event& event) 
    { 
     std::cout << "DerivedState::onEvent\n"; 
    } 

}; 

struct Context 
{}; 


int main() 
{ 
    DerivedState ds; 
    Context context; 
    ds.onEvent(context, Event()); 
} 

: は、いくつかのテストの後、私は次のコードスニペットを分離しました私には完全に合法的に見え、gcc、clang、icc(そして期待どおりに動作します)でうまくコンパイルされます。いくつかの追加のテストの後

、私はDerivedStateを導出する際にCRTPパターンを避ける場合は、コードが正常にコンパイルされることを見つける:

#include <iostream> 

struct Event 
{}; 

struct State 
{ 
public: 
    template<typename Fsm> 
    void onEvent(Fsm& fsm, const Event& event) 
    { 
     std::cout << "State::onEvent\n"; 
    } 

}; 

struct DerivedState 
    : State 
{ 
public: 
    using State::onEvent; 

    template<typename Fsm> 
    void onEvent(Fsm& fsm, const Event& event) 
    { 
     std::cout << "DerivedState::onEvent\n"; 
    } 

}; 

struct Context 
{}; 


int main() 
{ 
    DerivedState ds; 
    Context context; 
    ds.onEvent(context, Event()); 
} 

誰がこの違いを説明できますか? Microsoftコンパイラは標準に準拠していませんか?宣言を使用cppreference documentation(強調鉱山)によれば

答えて

6

は、このような由来のパブリックメンバとしてベースの保護部材を露出するように、派生クラス定義に基本クラスのメンバーを導入します。この場合、ネストされた名前指定子は、定義されているものの基本クラスに名前を付ける必要があります。名前がベースクラスのオーバーロードされたメンバ関数の名前である場合、その名前を持つすべてのベースクラスメンバ関数が導入されます。 派生クラスに既に同じ名前、パラメーターリスト、および資格を持つメンバーがある場合、派生クラスメンバーは、基底クラスから導入されたメンバーをで非表示にします(矛盾しません)。

したがって、基本的にメソッドの宣言を使用しても実際には何も行われません(メソッドは公開されているので、usingは不要です)。あなたの派生クラスは単にonEventメソッドを隠します。

他のコンパイラは正しく、マイクロソフトは間違っています。

関連する問題