C+ 11-声明非静态数据成员为' auto'

发布于 2025-02-12 12:06:31 字数 276 浏览 1 评论 0 原文

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

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

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

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

Does C++11 allow declaring non-static data members as 'auto' if they are initialized in the declaration? For example:

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

GCC 4.7 rejects the above code, while it accepts int x = 5;.

Assuming this is not a compiler bug but rather the standard really doesn't allow it, why not? It would be just as useful as declaring local variables auto.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

策马西风 2025-02-19 12:06:31

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

自动类型分配器也可以用于声明变量
选择语句(6.4)或迭代语句的条件
(6.5),在新型-ID或类型ID中的类型分类器seq中
新表达(5.3.4),在范围内,并在宣布
静态数据成员带有出现在类定义的成员规范中的支架或平等限制器(9.4.2)。

我发现它的理由是静态的在这里在评论中解释。

一个民族不喜欢允许自动类型的特定符
非派系。从电子邮件到作者:

 模板< T&GT级
    构造mytype:t {
      自动data = func();
      静态const size_t erm = sizeof(data);
    };
 

为了确定X的布局,我们现在有2相平均名称查找和ADL。请注意,Func可以是类型或功能;
它可以在t,mytype的命名空间中找到,
t的命名空间在实例化时,全局名称空间,一个
匿名名称空间或任何命名空间受使用指令的约束。
小心翼翼,我们可能会为运气提供一些概念_映射查找。
根据标头包含的顺序,我什至可能会为ADL获得不同的结果,并打破一个定义规则 -
不需要诊断。

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

因此,基本上,根据标头包含的顺序,数据的类型可能会大不相同。当然, auto x = 5; 不需要依赖2相名称查找或ADL,但是,我假设他们将其制定为“毯子”规则,因为否则,他们将必须为每种用例制定个人规则,这将使事情变得非常复杂。

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

The rule for prohibiting non-static members is in 7.1.6.4 clause 4:

The auto type-specifier can also be used in declaring a variable in
the condition of a selection statement (6.4) or an iteration statement
(6.5), in the type-specifier-seq in the new-type-id or type-id of a
new-expression (5.3.4), in a for-range-declaration, and in declaring a
static data member with a brace-or-equal-initializer that appears within the member-specification of a class definition (9.4.2).

I found the rationale for it being static here which reflects how James McNellis explains it in the comment.

One national body dislikes allowing the auto type-specifier for
non-statics. From an e-mail to the authors:

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

In order to determine the layout of X, we now have 2-phase name lookup and ADL. Note that func could be either a type or a function;
it may be found in T, the namespace of MyType, the associated
namespace(s) of T when instantiated, the global namespace, an
anonymous namespace, or any namespaces subject to a using directive.
With care we could probably throw some concept_map lookup in for luck.
Depending on the order of header inclusion I might even get different results for ADL, and break the One Definition Rule - which
is not required to be diagnosed.

Because of this controversy, the authors no longer propose that auto
be allowed for non-static data members.

So, basically depending on the order of header inclusion, the type of data could be very different. Of course, auto x = 5; would not need to depend on 2-phase name lookup or ADL, however, I'm a assuming that they made it a "blanket" rule because otherwise, they would have to make individual rules for every use case which would make things very complicated.

In the same paper, the author proposes eliminating this restriction, however, it seems this proposal has been rejected probably due to the above rationale and also so that expected behavior can be the same no matter what the initializer is.

情定在深秋 2025-02-19 12:06:31

对于其他人:

使用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

您可以将语言误用在提交中使用位置new和offset_of引用不存在类的lambda,但这是可笑的,不需要。

For others:

Using C++17 this is indirectly (automatic deduction of non-static member type) possible. You need to use templates and deduction guides to make it happen:

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>>;

I don't know how but this auto members really need to make it into the language without them certain patterns are next to impossible.

The scenario above does not work if the lambda captures a member of class by reference. This is a useful pattern for, highly compensable classes that avoid the use of type erased functions. Something I regularly do on embedded systems.

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

You can mangle the language into submission allowing a lambda to reference a member of a non-existent class using placement-new and offset_of but that is ludicrous and shouldn't be required.

您的好友蓝忘机已上羡 2025-02-19 12:06:31

后来的讨论是完整级上下文任何成员的类型都不是。另一个理由是,

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

尽管完全忽略了默认会员初始化器的 type ,否则将是奇怪的。

Later discussion was publicly summarized in 2014: the critical point was that a default member initializer is a complete-class context but the type of any member is not. One further bit of rationale is that it would be odd to have

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

use the type of the default member initializer despite completely ignoring it otherwise.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文