为啥此 C++ 代码仅在 Microsoft 编译器上具有模棱两可的方法调用?
Posted
技术标签:
【中文标题】为啥此 C++ 代码仅在 Microsoft 编译器上具有模棱两可的方法调用?【英文标题】:Why has this C++ code an ambiguous method call only on Microsoft compiler?为什么此 C++ 代码仅在 Microsoft 编译器上具有模棱两可的方法调用? 【发布时间】:2017-12-16 20:36:42 【问题描述】:我正在尝试在 microsoft C++ 编译器 14.1 (Visual Studio 2017) 上编译一个库,但由于对类方法的不明确调用,我遇到了一个奇怪的错误。 经过一些测试,我隔离了以下代码sn-p:
#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 上编译良好(并且表现也符合预期)。
经过一些额外的测试,我发现如果我在派生DerivedState
时避免使用 CRTP 模式,代码编译得很好:
#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 编译器不符合标准吗?
【问题讨论】:
【参考方案1】:根据cppreference documentation(强调我的)
使用声明将基类的成员引入派生类定义中,例如将基类的受保护成员公开为派生的公共成员。在这种情况下,nested-name-specifier 必须命名一个被定义的基类。如果名称是基类的重载成员函数的名称,则引入具有该名称的所有基类成员函数。 如果派生类已经有一个具有相同名称、参数列表和限定条件的成员,则派生类成员隐藏或覆盖(不冲突)从基类引入的成员。
所以基本上你对该方法的 using 声明并没有真正做任何事情(无论如何该方法是公共的,所以不需要using
)。您的派生类只是隐藏 onEvent
方法。
所以其他编译器是对的,微软是错的。
【讨论】:
以上是关于为啥此 C++ 代码仅在 Microsoft 编译器上具有模棱两可的方法调用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我会收到错误“不安全代码可能仅在使用 /unsafe 编译时出现”?