可变匿名结构

时间:2016-05-08 14:18:26

标签: c++ struct clang constants mutable

我想定义一个包含多个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;会出错:

  

错误:无法使用const限定类型'const X'

分配给变量'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;
}

也会出错:

  

错误:无法在const成员函数'f'

中分配给非静态数据成员      

注意:成员函数'main():: X :: f'在这里声明为const           void f()const {i = 1; }

1 个答案:

答案 0 :(得分:4)

麻烦来自于匿名E152: Cannot open /Users/Mikkel/.vim/bundle/nerdtree/doc/tags for writing struct的非标准(在C ++中)使用的混合。后者是一个存储类说明符,用于成员而不是类型。

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

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

mutable

Live demo

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

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

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

Online demo

标准说什么?

standatad C ++不允许使用匿名结构。匿名结构是compiler extension for C11 compatibility

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

  

9.5 / 6:类范围内的匿名联合声明中不允许存储类。

因此在编译以下代码时:

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

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

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

我认为允许在匿名结构上使用存储类说明符(并且显然忽略它)并为匿名联合发出错误并不一致。据我说,这将被报告为编译器错误。在任何情况下,您都应该采用备选方案1(便携式和兼容性)或备选方案2(依赖于编译器,但更符合标准)。