可变匿名结构

Mutable anonymous struct

我想定义一个包含多个 mutable 字段的聚合(将其保存在 std::setstd::priority_queue 中并在将来修改它,肯定会保存容器不变量)。我尝试了以下语法并成功编译:

#include <cstdlib>

int
main()
{
    struct X
    {
        mutable struct 
        {
            int i;
            int j;            
        };
    };
    X const x{};
    //x.i = 1;
    return EXIT_SUCCESS;
}

Live example for clang 3.8.

但是语句x.i = 1;报错:

error: cannot assign to variable 'x' with const-qualified type 'const X'

我的目的是将大量连续的文件分组,然后将 mutable 关键字应用于该组。

这个语法有错吗?如果是这样,编译器制造商允许这种语法的意图是什么?

附加:

代码:

#include <cstdlib>

int
main()
{
    struct X
    {
        mutable struct 
        {
            int i;
            int j;            
        };
        void f() const { i = 1; }
    };
    X const x{};
    //x.i = 1;
    x.f();
    return EXIT_SUCCESS;
}

也报错:

error: cannot assign to non-static data member within const member function 'f'

note: member function 'main()::X::f' is declared const here void f() const { i = 1; }

麻烦来自匿名 structmutable 的非标准(在 C++ 中)用法的混合。后者是一个存储 class 说明符,用于成员而不是类型。

备选方案 1:为您的匿名结构定义一个中间成员:

您可以根据标准 C++ 的规则定义一个可变的成员:

struct X
{
    mutable struct 
    {
        int i;
        int j;            
    } y;
};
X const x{};
x.y.i = 1;

Live demo

备选方案 2:使匿名结构中的每个成员都可变:

您可以另外将结构中的成员定义为可变的。当匿名结构将这些成员合并到封闭结构中时,可变 属性 将被传递:

struct X
{
    struct 
    {
        mutable int i;
        mutable int j;            
    };
};

Online demo

标准怎么说?

C++ 标准不允许匿名结构。匿名结构是 compiler extension for C11 compatibility.

C++ 标准允许匿名联合。但它设置了限制,特别是:

9.5/6: A storage class is not allowed in a declaration of an anonymous union in a class scope.

所以在编译如下代码时:

  struct X
    {
        mutable union 
        {
            int i;
            int j;            
        };
    }; 

编译器应该并且将会发出一个非常具体的错误:

prog.cpp:11:13: error: a storage class on an anonymous aggregate in class  scope is not allowed
         mutable union 

我认为允许在匿名结构上使用存储 class 说明符(并且显然忽略它)并为匿名联合发出错误是不一致的。根据我的说法,这应该被报告为编译器错误。无论如何,您应该采用备选方案 1(可移植且兼容)或备选方案 2(依赖于编译器,但更符合标准)。