2017-07-12 20 views
12

मैं माइक्रोसॉफ्ट C++ कम्पाइलर 14.1 (विजुअल स्टूडियो 2017) लेकिन मैं एक अजीब त्रुटि हो रही है पर एक पुस्तकालय संकलित करने के लिए कोशिश कर रहा हूँ एक वर्ग विधि के लिए एक अस्पष्ट कॉल की वजह से।यह सी ++ कोड केवल माइक्रोसॉफ्ट कंपाइलर पर एक संदिग्ध विधि कॉल क्यों है?

#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()); 
} 

मैं निम्नलिखित उत्पादन प्राप्त:

1> C: \ Users \ pmas \ दस्तावेज \ दृश्य स्टूडियो

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 
{}; 

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()); 
} 

किसी को भी इस अंतर की व्याख्या कर सकते:

कुछ अतिरिक्त परीक्षण के बाद, मुझे लगता है कि कोड ठीक संकलित अगर मैं DerivedState पाने में CRTP पैटर्न से बचने पता चला? क्या माइक्रोसॉफ्ट कंपाइलर मानक के अनुरूप नहीं है?

उत्तर

6

cppreference documentation (जोर मेरा) के अनुसार

का उपयोग करना-घोषणा व्युत्पन्न वर्ग परिभाषा में एक आधार वर्ग के एक सदस्य का परिचय है, सार्वजनिक सदस्य के रूप में आधार के एक संरक्षित सदस्य बेनकाब करने के लिए इस तरह के रूप व्युत्पन्न की। इस मामले में, नेस्टेड-नाम-विनिर्देशक को परिभाषित किए जाने वाले आधार वर्ग का नाम होना चाहिए। यदि नाम बेस क्लास के ओवरलोडेड सदस्य फ़ंक्शन का नाम है, तो उस नाम के साथ सभी बेस क्लास सदस्य फ़ंक्शंस पेश किए जाते हैं। व्युत्पन्न वर्ग पहले से ही एक ही नाम, पैरामीटर सूची, और योग्यता के साथ एक सदस्य है, तो व्युत्पन्न वर्ग सदस्य छुपाता है या ओवरराइड करता है (के साथ संघर्ष नहीं करता है) के सदस्य है कि आधार वर्ग से शुरू की है।

तो मूल रूप से विधि के लिए अपने घोषणापत्र का उपयोग कर वास्तव में कुछ (विधि वैसे भी सार्वजनिक था, इसलिए using की कोई आवश्यकता नहीं) नहीं करता है। आपकी व्युत्पन्न कक्षा बस onEvent विधि छुपाती है।

तो अन्य compilers ठीक कह रहे हैं, और माइक्रोसॉफ्ट गलत है।

संबंधित मुद्दे