2016-10-04 65 views
4

我玩弄的FSM的templated implementation和如下我遇到的歧義:模板實例歧義

/home/permal/code/FSM/Test/../FSM/dist/include/FSM.h: In instantiation of ‘void fsm::FSM<FSMBaseState>::Event(std::unique_ptr<EventType>) [with EventType = AddEvent; FSMBaseState = EventBaseState]’: 
/home/permal/code/FSM/Test/test.cpp:83:44: required from here 
/home/permal/code/FSM/Test/../FSM/dist/include/FSM.h:59:4: error: request for member ‘Event’ is ambiguous 
    myCurrent->Event(std::move(event)); 
    ^
In file included from /home/permal/code/FSM/Test/../FSM/dist/include/FSM.h:12:0, 
       from /home/permal/code/FSM/Test/test.cpp:8: 
/home/permal/code/FSM/Test/../FSM/dist/include/EventReceiver.h:15:15: note: candidates are: void fsm::EventReceiver<EventType>::Event(std::unique_ptr<_Tp>) [with EventType = SubtractEvent] 
    virtual void Event(std::unique_ptr<EventType> event) = 0; 
      ^
/home/permal/code/FSM/Test/../FSM/dist/include/EventReceiver.h:15:15: note:     void fsm::EventReceiver<EventType>::Event(std::unique_ptr<_Tp>) [with EventType = AddEvent] 
In file included from /home/permal/code/FSM/Test/test.cpp:8:0: 
/home/permal/code/FSM/Test/../FSM/dist/include/FSM.h: In instantiation of ‘void fsm::FSM<FSMBaseState>::Event(std::unique_ptr<EventType>) [with EventType = SubtractEvent; FSMBaseState = EventBaseState]’: 
/home/permal/code/FSM/Test/test.cpp:91:50: required from here 
/home/permal/code/FSM/Test/../FSM/dist/include/FSM.h:59:4: error: request for member ‘Event’ is ambiguous 
    myCurrent->Event(std::move(event)); 

所以我的問題是爲什麼編譯器不能選擇正確的選項,即使它闡明瞭這有兩個可能的候選人,其中一個是正確的。

我希望下面的代碼,就足以說明問題,剩下的就是可在GitHub

這是歧義發生的類和方法:

template<typename FSMBaseState> 
class FSM 
{ 
public: 
    ... 

    template<typename EventType> 
    void Event(std::unique_ptr<EventType> event) 
    { 
     if(HasState()) 
     { 
      // This way of calling causes ambiguous method lookup during template instantiation 
      myCurrent->Event(std::move(event)); 

      // casting to the correct type works, but is it really needed? 
      // auto* s = myCurrent.get(); 
      // static_cast<EventReceiver<EventType>*>(s)->Event(std::move(event)); 
     } 
    } 

}; 

上述方法要麼叫作爲fsm.Event(std::make_unique<AddEvent>());fsm.Event(std::make_unique<SubractEvent>());

在上述事件myCurrent() - 方法是下面的類的一個實例:

class EventBaseState 
: public fsm::BaseState<EventBaseState>, 
     public fsm::EventReceiver<AddEvent>, 
     public fsm::EventReceiver<SubtractEvent> 
{ 
public: 
EventBaseState(const std::string& name, fsm::FSM<EventBaseState>& fsm) : 
     BaseState(name, fsm) 
{} 

}; 

其中EventReceiver定義如下:

template<typename EventType> 
class EventReceiver 
{ 
public: 
    virtual void Event(std::unique_ptr<EventType> event) = 0; 
}; 

更新

從一個新的角度事情來看,我結束了一個純虛函數的Event<T>(...)方法,這實際上是什麼我真的很想,因爲EventBaseState班應該是抽象的。

class EventBaseState 
    : public fsm::BaseState<EventBaseState>, 
     public fsm::EventReceiver<AddEvent>, 
     public fsm::EventReceiver<SubtractEvent> 
{ 
public: 
    EventBaseState(const std::string& name, fsm::FSM<EventBaseState>& fsm) : 
      BaseState(name, fsm) 
    {} 

    virtual void Event(std::unique_ptr<AddEvent> event) override = 0; 
    virtual void Event(std::unique_ptr<SubtractEvent> event) override = 0; 
}; 

當然,Chajnik-U提供的解決方案也適用。

+0

'myCurrent->事件(標準::移動(事件));'這是重要的線。什麼是'myCurrent'和'event'的類型?在調用'myCurrent-> Event(std :: move(event))的函數中究竟是如何確切定義了這兩個變量的?' –

+0

@AaronMcDaid問題在於:'myCurrent'是'EventBaseState','event'是'std :: unique_ptr '或'std :: unique_ptr '。 – Rakete1111

回答

3

基類的方法在通過派生類實例調用時不參與「跨類」重載。 你必須把

using EventReceiver<AddEvent>::Event; 
using EventReceiver<SubtractEvent>::Event; 

EventBaseState迫使這兩種方法是通過超載可見。 對於從視標準的點更多的細節(與簡化的例子),請參見這裏:

Why do multiple-inherited functions with same name but different signatures not get treated as overloaded functions?

+0

你很可能是正確的,我會在試用它時將其標記爲答案。我必須說編譯器的消息真的會讓你走錯了路 - 它實際上表明有兩個候選可用,但然後忽略它們。 – Per