Я играл с 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
в приведенном выше Event() - метод представляет собой экземпляр следующего класса:
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;
};
Update
Глядя на вещи под новым углом зрения, я закончил с чисто виртуальными функциями для 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 тоже работает.
'myCurrent-> Event (станд :: хода (событие));' Это важная строка , Какой тип 'myCurrent' и' event'? Как именно эти две переменные объявлены в функции, вызывающей 'myCurrent-> Event (std :: move (event)),' –
@AaronMcDaid. В вопросе: 'myCurrent' -' EventBaseState', а 'event' -' std :: unique_ptr 'или' std :: unique_ptr '. –
Rakete1111