C++ 外部函数指针声明和类型推断定义

C++ 外部函数指针声明和类型推断定义,c++,c++11,function-pointers,C++,C++11,Function Pointers,我最近收到了一个被clang++接受但不被g++接受的代码,我想知道哪一个是正确的 复制这种行为的极简主义代码非常简短,而且本身就是空谈,因此我认为解释会非常复杂 以下是包含外部指针声明的标头: //(guards removed for simplicity) : #include <type_traits> using ptr_func = std::add_pointer<void()>::type; extern ptr_func pointer; gcc产

我最近收到了一个被clang++接受但不被g++接受的代码,我想知道哪一个是正确的

复制这种行为的极简主义代码非常简短,而且本身就是空谈,因此我认为解释会非常复杂

以下是包含外部指针声明的标头:

//(guards removed for simplicity) :
#include <type_traits>

using ptr_func = std::add_pointer<void()>::type;

extern ptr_func pointer;
gcc产生的错误如下:

g++ -c function.cc -std=c++14
function.cc:5:6: error: conflicting declaration ‘auto pointer’
 auto pointer = &foo;
      ^
In file included from function.cc:1:0:
function.hh:5:17: note: previous declaration as ‘void (* pointer)()’
 extern ptr_func pointer;
                 ^
Clang接受此代码,没有任何错误/警告。并将指针定义替换为:

decltype(foo)* pointer = &foo;
被gcc接受


在我看来,clang是正确的,但我不确定,所以我想知道clang是否过于宽容,或者gcc是否应该接受它。

这肯定是gcc中的一个缺陷。下面是一个简单的例子:

int foo;
extern int* ptr;
auto ptr = &foo;
有趣的是,如果
extern
auto
声明被颠倒,gcc会很高兴

这似乎与去年报道的情况相同

相关条款为[basic.link]/10:

在所有类型调整之后(在此期间,typedefs(7.1.3)被其定义替换),类型 引用给定变量或函数的所有声明所指定的值应相同,但声明除外 对于数组,对象可以指定因是否存在主数组而不同的数组类型 绑定(8.3.4)。对类型标识违反此规则不需要诊断


到底是哪个GCC版本?我用g++4.9.1和g++4.9.2测试了它。我已经用
std::add_pointer::type在Ideone上测试了代码(认为它至少使用了g++4.9.1)(对我来说更像是一个有效的函数指针声明)。但它也不接受这一点。看起来GCC的
std::add_pointer
实现与函数指针不兼容。@πάνταῥεῖ <代码>标准::添加指针::类型将是指向指针的指针。这里的问题不在于工作正常的
add_pointer
,而在于
auto
推断类型与先前声明的类型的比较。这里有一个简单的例子,根本不涉及指针:
extern int x;自动x=1;int main(){}
。它也适用于clang,但不适用于gcc。
foo()
实际上是OP示例中的一个函数?这有区别吗?@πάνταῥεῖ 我不明白为什么会有什么不同<代码>空洞(*)()/Cord>是数据类型,GCC全部正确地执行其类型计算。如果这是GCC中的一个错误,那么Visual C++ 2017(V19.1024930)也有同样的错误。MSVC给出
错误C2373:重新定义;不同类型的修饰符
。所以你是说在3个主要的编译器实现中,有2个错误了,而且即使在最新版本中,这个错误仍然存在。(测试)@greatwolf是的,看起来是这样。请注意,icc同意clang,所以它更像是一个50对50的分割。@LightnessRacesinOrbit这是[dcl.spec.auto]/4,不是吗?([dcl.spec.auto]/3在C++11中)。
int foo;
extern int* ptr;
auto ptr = &foo;