表达式的不同编译器行为:auto p {make_pointer()}; [英] Different compiler behavior for expression: auto p {make_pointer()};

查看:177
本文介绍了表达式的不同编译器行为:auto p {make_pointer()};的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下程序的正确行为是什么?

Which is the correct behaviour for the following program?

// example.cpp

#include <iostream>
#include <memory>

struct Foo {
  void Bar() const {
    std::cout << "Foo::Bar()" << std::endl;
  }
};

std::shared_ptr<Foo> MakeFoo() {
  return std::make_shared<Foo>();
}

int main() {
  auto p { MakeFoo() };
  p->Bar();  
}



当我在Linux RHEL 6.6工作站中编译它时, :

When I compile it in my Linux RHEL 6.6 workstation, I obtain the following results:

$ g++ -v
gcc version 5.1.0 (GCC)
$ g++ example.cpp -std=c++14 -Wall -Wextra -pedantic
$ ./a.out
Foo::Bar()

$ clang++ -v
clang version 3.6.0 (trunk 217965)
$ clang++ example.cpp -std=c++14 -Wall -Wextra -pedantic
example.cpp:16:4: error: member reference type 'std::initializer_list<std::shared_ptr<Foo> >' is not a pointer; maybe you meant to use '.'?
      p->Bar();
      ~^~
example.cpp:16:6: error: no member named 'Bar' in 'std::initializer_list<std::shared_ptr<Foo> >'
      p->Bar();
      ~  ^
    2 errors generated.

$ icpc -v
icpc version 15.0.3 (gcc version 5.1.0 compatibility)
$ icpc example.cpp -std=c++14 -Wall -Wextra -pedantic
example.cpp(16): error: expression must have pointer type
    p->Bar();
    ^
compilation aborted for example.cpp (code 2)


推荐答案

Tl; DR

此行为受制于提案和Evolution工作组问题。关于这是否被认为是C ++ 14缺陷或C ++ 1z提议存在一些模糊性。如果事实证明是一个C ++ 14缺陷,然后gcc的行为是正确的C + + 14。另一方面,如果这真的是C ++ 1z提议,那么clang和icpc表现出正确的行为。

This behavior is subject to a proposal and an Evolution Working Group issue. There is some ambiguity as to whether this is considered a C++14 defect or a C++1z proposal. If it turns out to be a C++14 defect then gcc's behavior is correct for C++14. On the other hand if this is really a C++1z proposal then clang and icpc are exhibiting correct behavior.

详细

这种情况看起来像是 N3681 说:

It looks like this case is covered by N3681 which says:


自动和支撑的初始化器会导致可教导性问题;我们想要
教人们使用统一初始化,但我们需要
专门告诉程序员避免使用大括号auto。在C ++ 14中,我们
现在有更多的情况,其中汽车和大括号有问题;返回类型
函数的扣除部分避免了这个问题,因为返回
,braced-list将不会工作,因为它不是一个表达式。然而,返回
从支持的初始化器初始化的自动变量仍然返回
一个initializer_list,邀请未定义的行为。 Lambda init
捕获有相同的问题。本文提出更改
括号初始化自动不推导到初始化列表,和
禁用括号初始化自动为支持初始化有多个元素
的情况。

Auto and braced initializers cause a teachability problem; we want to teach people to use uniform initialization, but we need to specifically tell programmers to avoid braces with auto. In C++14, we now have more cases where auto and braces are problematic; return type deduction for functions partially avoids the problem, since returning a braced-list won't work as it's not an expression. However, returning an auto variable initialized from a braced initializer still returns an initializer_list, inviting undefined behaviour. Lambda init captures have the same problem. This paper proposes to change a brace-initialized auto to not deduce to an initializer list, and to ban brace-initialized auto for cases where the braced-initializer has more than one element.

并提供以下示例:


auto x = foo(); // copy-initialization
auto x{foo}; // direct-initialization, initializes an initializer_list
int x = foo(); // copy-initialization
int x{foo}; // direct-initialization


目前正确, clang的最新版本提供此警告:

So I think clang is currently correct, the latest version of clang provides this warning:


警告:直接列表初始化具有推导类型的变量
将在Clang的未来版本中改变含义; insert a'='to
避免行为的改变[-Wfuture-compat]

warning: direct list initialization of a variable with a deduced type will change meaning in a future version of Clang; insert an '=' to avoid a change in behavior [-Wfuture-compat]

EWG问题161 N3922

如Praetorian所说,建议这是一个C ++ 14缺陷:

As Praetorian notes the proposal recommends this is a C++14 defect:


EWG的方向是我们认为这是C ++ 14中的缺陷。

Direction from EWG is that we consider this a defect in C++14.

但是clang的 C ++ 1z实现状态说明这是一个未实现的C ++ 1z提案。

but clang's C++1z implementation status notes this as a C++1z proposal which is not implemented.

因此,如果这是一个C ++ 14缺陷,这将使gcc正确,但我不清楚,如果这是一个缺陷或提案。

So if this is a C++14 defect, that would make gcc correct but it is not clear to me if this is really a defect or a proposal.

TC在中的评论,它似乎是蚌蜊开发商意在支持这一点。它没有发生,也不清楚为什么。

T.C. points out in a comment here that it seems like the clang developers do intended to back-port this. It has not happened and it is not clear why.

这篇关于表达式的不同编译器行为:auto p {make_pointer()};的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆