繁体   English   中英

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

[英]C++11 - declaring non-static data members as 'auto'

如果在声明中初始化非静态数据成员,C++11 是否允许将非静态数据成员声明为“自动”? 例如:

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

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

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

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

auto 类型说明符还可用于在选择语句 (6.4) 或迭代语句 (6.5) 的条件中声明变量,在 new-type-id 或 type-id 的 type-specifier-seq 中新表达式 (5.3.4),在 for-range-declaration 中,以及在声明static 数据成员时,带有出现在 class 定义 (9.4.2) 的成员规范中的大括号或等号初始化器.

我发现它的理由是 static 这里反映了 James McNellis 如何在评论中解释它。

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

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

为了确定 X 的布局,我们现在有 2 阶段名称查找和 ADL。 请注意, func 可以是类型或 function; 它可以在 T、MyType 的命名空间、实例化时 T 的关联命名空间、全局命名空间、匿名命名空间或任何受 using 指令约束的命名空间中找到。 小心我们可能会抛出一些 concept_map 查找以求好运。 根据 header 包含的顺序,我什至可能会得到不同的 ADL 结果,并打破一个定义规则 - 这不需要被诊断。

由于这个争议,作者不再建议对非静态数据成员允许 auto 。

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

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

为他人:

使用 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 通过引用捕获 class 的成员,则上述方案不起作用 对于避免使用类型擦除函数的高度可补偿的类,这是一种有用的模式。 我经常在嵌入式系统上做的事情。

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

您可以将语言修改为提交,允许 lambda 使用 Placement-new 和 offset_of 引用不存在的 class 的成员,但这很荒谬,不应该是必需的。

后来的讨论在 2014 年被公开总结:关键点是默认成员初始化器是一个完整的类上下文,但任何成员的类型都不是。 还有一点理由是,如果有

std::vector<int> get_ints();
struct S {
  auto x=get_ints();
  S() : x(7,4) {}
};

使用默认成员初始化程序的类型,尽管完全忽略它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM