我正在玩templated implementation FSM并遇到如下歧义:
/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
类应该是抽象的。< / p>
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 :(得分:3)
当通过派生类实例调用时,基类的方法不参与“跨类”重载。 你必须放置
using EventReceiver<AddEvent>::Event;
using EventReceiver<SubtractEvent>::Event;
在EventBaseState
内部强制两个方法都可以通过重载看到。 有关标准的详细信息(简化示例),请参见此处: