为什么这C++只在编译器上编码一个不明确的方法调用Microsoft?



我正在尝试在Microsoft C++编译器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::onEventn";
}
};
struct DerivedState
: State<DerivedState>
{
public:
using State::onEvent;
template<typename Fsm>
void onEvent(Fsm& fsm, const Event& event)
{
std::cout << "DerivedState::onEventn";
}
};
struct Context
{};

int main()
{
DerivedState ds;
Context context;
ds.onEvent(context, Event());
}

我得到以下输出:

1>c:\users\pmas\documents\Visual Studio

2017projectsconsoleapplication3consoleapplication3consoleapplication3.cpp(87): error C2668: 'DerivedState::onEvent': ambiguous call to overloaded function
1>c:userspmasdocumentsvisual studio 2017projectsconsoleapplication3consoleapplication3consoleapplication3.cpp(59): note: could be 'void DerivedState::onEvent<Context>(Fsm &,const Event &)'
1>        with
1>        [
1>            Fsm=Context
1>        ]
1>c:userspmasdocumentsvisual studio 2017projectsconsoleapplication3consoleapplication3consoleapplication3.cpp(45): note: or       'void State<DerivedState>::onEvent<Context>(Fsm &,const Event &)'
1>        with
1>        [
1>            Fsm=Context
1>        ]
1>c:userspmasdocumentsvisual studio 2017projectsconsoleapplication3consoleapplication3consoleapplication3.cpp(87): note: while trying to match the argument list '(Context, Event)'

在我看来,该代码完全合法,并且在 gcc、clang 和 icc 上编译良好(并且也按预期运行(。

经过一些额外的测试,我发现如果我在派生DerivedState中避免使用 CRTP 模式,代码可以很好地编译:

#include <iostream>
struct Event
{};
struct State
{
public:
template<typename Fsm>
void onEvent(Fsm& fsm, const Event& event)
{
std::cout << "State::onEventn";
}
};
struct DerivedState
: State
{
public:
using State::onEvent;
template<typename Fsm>
void onEvent(Fsm& fsm, const Event& event)
{
std::cout << "DerivedState::onEventn";
}
};
struct Context
{};

int main()
{
DerivedState ds;
Context context;
ds.onEvent(context, Event());
}

谁能解释这种差异?微软编译器不符合标准吗?

根据 cpp 首选项文档(强调我的(

using-声明将基类的成员引入派生类定义中,例如将基的受保护成员公开为派生的公共成员。在这种情况下,嵌套名称说明符必须命名正在定义的基类。如果名称是基类的重载成员函数的名称,则引入具有该名称的所有基类成员函数。如果派生类已具有具有相同名称、参数列表和限定条件的成员,则派生类成员将隐藏或重写从基类引入的成员(不冲突(。

所以基本上你对方法的使用声明并没有真正做任何事情(无论如何,该方法都是公开的,所以不需要using(。 派生类只是隐藏onEvent方法。

所以其他编译器是对的,微软是错的。

相关内容

  • 没有找到相关文章

最新更新