Я пытаюсь скомпилировать библиотеку на microsoft С++ compiler 14.1 (Visual Studio 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\documents\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)'
Код выглядит мне совершенно законным и компилируется в gcc, clang и icc (и ведет себя так же, как и ожидалось).
После некоторого дополнительного тестирования я узнаю, что код компилируется отлично, если я избегаю CRTP-шаблона при выводе DerivedState
:
#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 не соответствует стандарту?