【问题标题】:Mutable anonymous struct可变匿名结构
【发布时间】:2016-09-03 04:55:59
【问题描述】:

我想定义一个包含多个 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 无效 f() 常量 { i = 1; }

【问题讨论】:

  • mutable 关键字仅对成员函数内部的成员有意义。
  • X 没有名为 i 的数据成员。你确定这个例子重现了你的真实用例吗?
  • @juanchopanza 我确定。我真的(相信我!)确实想对多个字段进行分组并同时将mutable 类型说明符应用于所有字段。
  • 好吧,你不能那样做,因为X没有名为i的成员。
  • @juanchopanza 我认为他使用了未命名的结构 as allowed by C11 但不是 C++。我猜这种非标准用法与标准 C++ mutable 的混合不会按预期工作。

标签: c++ struct clang constants mutable


【解决方案1】:

问题在于匿名@​​987654324@ 和mutable 的非标准(在C++ 中)使用之间的混合。后者是一个存储类说明符,用于成员而不是类型。

备选方案 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:类范围内的匿名联合声明中不允许存储类。

所以在编译以下代码时:

  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 

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

【讨论】:

  • 我的用法没有错,因为我最初的需要。标准原因可能是错误的,但我的意图已明确描述。我想要我想要的。
  • @Orient 你的用法完全不正确。这就是编译器试图告诉你的。
  • @juanchopanza 我完全同意。但是如果不正确,为什么编译器允许我定义mutable匿名结构?
  • @Orient,Coliru 的 GCC 不接受它。 Clang 明确表示匿名结构是 GNU 扩展。在该扩展的文档中,也许有更多关于它为什么接受 mutable 而没有声明变量(mutable 适用于变量)的信息。
  • @chris mutable 据我所知仅适用于数据成员声明,​​不是吗?
猜你喜欢
  • 1970-01-01
  • 2014-01-14
  • 2013-04-18
  • 2020-10-28
  • 2016-07-23
  • 2019-11-17
  • 2018-03-28
  • 2015-02-23
  • 1970-01-01
相关资源
最近更新 更多