C++ 外部函数指针声明和类型推断定义
我最近收到了一个被clang++接受但不被g++接受的代码,我想知道哪一个是正确的 复制这种行为的极简主义代码非常简短,而且本身就是空谈,因此我认为解释会非常复杂 以下是包含外部指针声明的标头: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产
//(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;