1

以下代码从 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为“不同类型的实体”:

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 之前也不存在的 vexing-parse 警告(警告在这里但不在上面的事实是有道理的,警告在 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
}

没有警告或任何东西。

所以...这里发生了什么事?为什么在这些特定情况下“重新声明为不同类型的实体”只是一个问题SomeValue,并且仅从 GCC 11.1 开始,为什么不会closure(SomeValue)()遇到与SomeClass(SomeValue)()?

还有什么变化?GCC在这里正确吗?它是 GCC 11.x 中引入的新错误吗?或者也许是最终在 11.x 中修复的旧错误?或者根本不是一个错误,而其他的东西发生了变化?

我正在努力想出一个一致的解释。

4

1 回答 1

1

不同之处在于您的第一个代码段声明了一个全局存在的函数;您的所有其他声明都是本地实体。
(请注意,即使声明有效,您也无法调用该函数,因为它不存在。)

在最后一个片段中,closure不是类型,所以它不能是声明。

于 2022-02-28T13:25:18.043 回答