C ++ 11 - 将非静态数据成员声明为“auto”

时间:2012-07-03 00:28:40

标签: c++ c++11 auto variable-declaration

如果在声明中初始化了非静态数据成员,它们是否允许将非静态数据成员声明为“auto”?例如:

struct S
{
    auto x = 5;  // in place of 'int x = 5;', which is definitely allowed
};

GCC 4.7拒绝上述代码,但接受int x = 5;

假设这不是编译器错误,而是标准真的不允许它,为什么不呢?它与声明局部变量auto一样有用。

2 个答案:

答案 0 :(得分:60)

禁止非静态成员的规则见7.1.6.4第4条:

  

auto type-specifier也可用于声明变量   选择语句(6.4)或迭代语句的条件   (6.5),在a的new-type-id或type-id的type-specifier-seq中   new-expression(5.3.4),在for-range-declaration中,以及声明a   静态数据成员,其中包含一个括号或等于初始化程序,它出现在类定义的成员规范中(9.4.2)。

我发现它是静态here的基本原理,反映了James McNellis在评论中如何解释它。

  

一个国家机构不喜欢允许使用自动类型说明符   非静。从电子邮件到作者:

    template< class T >
    struct MyType : T {
      auto data = func();
      static const size_t erm = sizeof(data);
    };
     

为了确定X的布局,我们现在有两阶段名称查找和ADL。请注意,func可以是类型或函数;   它可以在T中找到,MyType的命名空间,关联的   实例化时T的名称空间,全局名称空间,一个   匿名命名空间,或任何使用using指令的命名空间。   小心翼翼,我们可能会为了运气而抛出一些concept_map查找。   根据标题包含的顺序,我甚至可能会得到不同的ADL结果,并打破一个定义规则 - 哪个   不需要被诊断出来。

     

由于这种争议,作者不再提出自动化   允许非静态数据成员。

因此,基本上取决于包含头的顺序,data的类型可能非常不同。当然,auto x = 5;不需要依赖于两阶段名称查找或ADL,但是,我假设他们将其作为“一揽子”规则,否则,他们必须为每个人制定单独的规则用例会使事情变得非常复杂。

在同一篇论文中,作者建议取消这一限制,但是,似乎这个提议可能由于上述原因而被拒绝,并且无论初始化程序是什么,预期行为都可以相同。

答案 1 :(得分:1)

对于其他人:

使用C ++ 17可以间接实现(自动推断非静态成员类型)。您需要使用模板和演绎指南才能实现:

template< class data_t>
struct MyType 
{
    data_t data;
    static constexpr auto data_size = sizeof(data_t);

    MyType( data_t && p_data ) : data(p_data) {}
};

template< class data_t>
MyType(data_t &&) -> MyType<std::remove_reference_t<data_t>>;

我不知道该怎么做,但是如果没有这些自动成员,某些模式几乎是不可能的。

如果lambda通过引用捕获类的成员,则上述方案不起作用。对于高度可补偿的类,这是有用的模式,可避免使用类型擦除的函数。我在嵌入式系统上经常做的事情。

https://godbolt.org/z/W-K9Uk

您可以将语言修改为提交状态,以使lambda可以使用placement-new和offset_of引用不存在的类的成员,但这很荒谬,不需要这样做。