从GCC 4.7.1到GCC 11.1:,以下代码编译没有问题
constexpr int SomeValue = 0;
void test () {
void (SomeValue) ();
}
在GCC 11.x上,它失败:
<source>:4:23: error: 'void SomeValue()' redeclared as different kind of entity
4 | void (SomeValue) ();
| ^
<source>:1:15: note: previous declaration 'constexpr const int SomeValue'
1 | constexpr int SomeValue = 0;
| ^~~~~~~~~
但是错误";重新声明为不同种类的实体";对我来说似乎很奇怪:除了模棱两可的解析可能性之外,范围是不同的。此外,自4.7.1(包括11.x(以来,这些测试都在GCC的所有版本上编译,即使AFAIK每一个都将SomeValue
重新定义为"1";不同类型的实体":
constexpr int SomeValue = 0;
void test1 () { typedef void (SomeValue) (); }
void test2 () { double SomeValue; }
void test3 () { using SomeValue = char *; }
void test4 () { void (* SomeValue) (); }
void test5 () { struct SomeValue { }; }
void test6 () { enum class SomeValue { }; }
作为一个相对不那么荒谬的例子,这个代码也以类似的方式从11.x开始失败:
constexpr int SomeValue = 0;
struct SomeClass {
explicit SomeClass (int) { }
void operator () () { }
};
void test () {
SomeClass(SomeValue)();
}
尽管在这种情况下,它前面有一个令人烦恼的解析警告,在11.x之前也不存在(警告在这里但不在上面的事实是有意义的,警告在11.x以前没有出现的事实是有趣的(:
<source>: In function 'void test()':
<source>:9:25: warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]
9 | SomeClass(SomeValue)();
| ^~
<source>: At global scope:
<source>:9:26: error: 'SomeClass SomeValue()' redeclared as different kind of entity
9 | SomeClass(SomeValue)();
| ^
<source>:1:15: note: previous declaration 'constexpr const int SomeValue'
1 | constexpr int SomeValue = 0;
| ^~~~~~~~~
Compiler returned: 1
但是等等!还有更多
这段代码——由于与上面相同的解析模糊性,我本以为在11.x上会失败——在所有版本的GCC(包括11.x(上编译得很好:
constexpr int SomeValue = 0;
auto closure = [] (int) {
return [] () { };
};
void test () {
closure(SomeValue)(); // <-- doesn't cause any problems
}
没有任何警告或任何东西。
所以。。。这是怎么回事?为什么CCD_ 2仅仅是一个问题;重新声明为不同种类的实体";在这些特定的情况下,并且只有在GCC 11.1之后,为什么closure(SomeValue)()
没有遇到与SomeClass(SomeValue)()
相同的问题?
还有什么变化?GCC在这里正确吗?这是GCC 11.x中引入的一个新错误吗?或者可能是在11.x中最终修复的一个旧错误?或者根本不是一个bug,其他东西也发生了变化?
我很难想出一个一致的解释。
不同之处在于,您的第一个代码片段声明了一个全局存在的函数;所有其他声明都是本地实体的
(请注意,即使声明有效,也不能调用该函数,因为它不可能存在。(
在最后一个代码段中,closure
不是类型,因此它不能是声明。