可变匿名结构
Mutable anonymous struct
我想定义一个包含多个 mutable
字段的聚合(将其保存在 std::set
或 std::priority_queue
中并在将来修改它,肯定会保存容器不变量)。我尝试了以下语法并成功编译:
#include <cstdlib>
int
main()
{
struct X
{
mutable struct
{
int i;
int j;
};
};
X const x{};
//x.i = 1;
return EXIT_SUCCESS;
}
但是语句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; }
麻烦来自匿名 struct
和 mutable
的非标准(在 C++ 中)用法的混合。后者是一个存储 class 说明符,用于成员而不是类型。
备选方案 1:为您的匿名结构定义一个中间成员:
您可以根据标准 C++ 的规则定义一个可变的成员:
struct X
{
mutable struct
{
int i;
int j;
} y;
};
X const x{};
x.y.i = 1;
备选方案 2:使匿名结构中的每个成员都可变:
您可以另外将结构中的成员定义为可变的。当匿名结构将这些成员合并到封闭结构中时,可变 属性 将被传递:
struct X
{
struct
{
mutable int i;
mutable int j;
};
};
标准怎么说?
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(依赖于编译器,但更符合标准)。
我想定义一个包含多个 mutable
字段的聚合(将其保存在 std::set
或 std::priority_queue
中并在将来修改它,肯定会保存容器不变量)。我尝试了以下语法并成功编译:
#include <cstdlib>
int
main()
{
struct X
{
mutable struct
{
int i;
int j;
};
};
X const x{};
//x.i = 1;
return EXIT_SUCCESS;
}
但是语句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; }
麻烦来自匿名 struct
和 mutable
的非标准(在 C++ 中)用法的混合。后者是一个存储 class 说明符,用于成员而不是类型。
备选方案 1:为您的匿名结构定义一个中间成员:
您可以根据标准 C++ 的规则定义一个可变的成员:
struct X
{
mutable struct
{
int i;
int j;
} y;
};
X const x{};
x.y.i = 1;
备选方案 2:使匿名结构中的每个成员都可变:
您可以另外将结构中的成员定义为可变的。当匿名结构将这些成员合并到封闭结构中时,可变 属性 将被传递:
struct X
{
struct
{
mutable int i;
mutable int j;
};
};
标准怎么说?
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(依赖于编译器,但更符合标准)。