在成员函数的默认参数中使用强类型枚举的成员

Usage of members of a strongly typed enum in a member function's default arguments

本文关键字:成员 强类型 枚举 参数 函数 默认      更新时间:2023-10-16

我主要使用g++,现在使用Visual Studio 2015。我想用vc++ 2015来构建我的项目,但我得到的错误消息是,在给定默认参数的函数中使用'::'无效,并使用前向声明的强类型enum。

下面是一些代码:
struct Foo
{
    //! Forward declaration of Bar
    enum class Bar : short;
    //! "Faulty" function with default argument
    void DoSmth(Bar aBar = Bar::Baz)
    {
        // ... code ...
    }
    //! Complete declaration of Bar
    enum class Bar : short
    {
        Baz
    };
};
int main() { }

在使用默认参数Bar::Baz:

声明函数DoSmth()时出现以下错误
test.cpp(7): error C2589: '::': illegal token on right side of '::'
test.cpp(7): error C2059: syntax error: '::'
test.cpp(17): fatal error C1903: unable to recover from previous error(s); stopping compilation

使用g++(在4.9和5.1下测试),代码编译得很好,但使用vc++ 2015就不行了。

我完全意识到我必须在使用but之前声明一些东西。仅仅是因为vc++ 2015没有在类的范围内查找Bar的完整声明和定义,但g++却这样做了吗?或者,也许c++只是采取完整的声明,并将其与前向声明"合并"(因为它们在相同的作用域中),从而使其对类完全可用?或者我只是错了,是完全不同的原因导致了这一切?

我可以忍受,为了使它在vc++ 2015中工作,我必须更改所有强类型枚举的声明。

但我也想知道这是为什么?

你的代码是有效的,vc14拒绝它是错误的。

根据N4527,现行标准工作草案,[9.2p2]:

类被认为是完全定义的对象类型(3.9)(或完整类型)在类说明符的结束}处。在类成员规范,类被认为是完整的函数体,默认参数,using-declarations introducing继承构造函数(12.9)、异常规范大括号或相等初始化式非静态数据成员(包括这些东西在嵌套类中)。否则就被认为是不完整的在它自己的类成员规范中。

在默认参数中,查找Bar::Baz需要Bar的完整定义,这在完整的类中可用,所以一切都很好。

也许现在的解决方法是将enum class的完整定义移动到DoSmith()的函数调用之前。