表达式的不同编译器行为:auto p {make_pointer()};

时间:2015-07-08 18:56:43

标签: c++ g++ c++14 clang++ icc

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

// 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工作站中编译它时,我得到以下结果:

$ 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)

1 个答案:

答案 0 :(得分:16)

铊; DR

此行为受提案和Evolution工作组问题的影响。关于这是否被认为是C ++ 14缺陷或C ++ 1z提案存在一些含糊之处。如果结果是C ++ 14缺陷那么gcc的行为对于C ++ 14是正确的。另一方面,如果这真的是一个C ++ 1z提案,那么clang和icpc表现出正确的行为。

详细

N3681似乎涵盖了这种情况:

  

自动和支撑的初始化程序会导致可教性问题;我们想   教人们使用统一初始化,但我们需要   特别告诉程序员避免使用auto括号。在C ++ 14中,我们   现在有更多的情况,汽车和大括号是有问题的;返回类型   因为返回,功能的扣除部分地避免了问题   支撑列表不起作用,因为它不是表达式。但是,回来了   从支撑的初始化程序初始化的自动变量仍然返回   initializer_list,邀请未定义的行为。 Lambda init   捕获具有相同的问题。本文提出改变一个   brace-initialized auto不推导到初始化列表,并且   ban brace-initialized auto用于braced-initializer具有的情况   不止一个元素。

并提供以下示例:

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目前是正确的,最新版本的clang提供了这个警告:

  

警告:使用推导类型直接列出变量的列表   将改变Clang未来版本的含义;插入一个'='   避免改变行为[-Wfuture-compat]

EWG issue 161 N3922为此采用C++1z implementation status notes

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

  

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

但clang的comment here这是一个未实现的C ++ 1z提案。

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

T.C。在seems like the clang developers中指出它Accessing appView from Cordova 5.0.0打算将其反向移植。它没有发生,也不清楚为什么。