GCC 允许 1 行声明多个指针,但不是非指针,具有不同的 const 限定符

GCC allows 1-line declaring of multiple pointers, but not non-pointers, with different const qualifiers

鉴于以下程序,GCC(g++,但我假设std::位也适用于 C),as can be seen on IDEone.com, 行为如下:

因此我的问题是:

我已经搜索过了,但没有成功。我面前确实有 n3797.pdf 打开,但我似乎还没有达到理解其语法规范的要求水平。 :( 所以希望有人可以根据需要进行评估和翻译。

请不要只说不要在一行中声明多个变量。我知道为什么不鼓励这样做,但我尽量不这样做。 FWIW,for 循环使它成为获得 const 结束迭代器的一种方式很诱人——如果所述迭代器是指针,这似乎是可能的,但如果它是 class,则不是。无论如何,我不要求代码审查。主题是为什么存在这种差异,与利用它的建议程度无关。

#include <iostream>
#include <type_traits>

int main()
{
    int i{42};

    int *p1 = &i, *const p2 = &i; // OK
    std::cout << std::is_const< decltype(p1) >::value << '\n'; // 0
    std::cout << std::is_const< decltype(p2) >::value << '\n'; // 1

    int *const p3 = &i, *p4 = &i; // OK
    std::cout << std::is_const< decltype(p3) >::value << '\n'; // 1
    std::cout << std::is_const< decltype(p4) >::value << '\n'; // 0

    int const l = i, m = i; // OK
    std::cout << std::is_const< decltype(l) >::value << '\n'; // 1
    std::cout << std::is_const< decltype(m) >::value << '\n'; // 1

    //int j = i, const k = i; // error: expected unqualified-id before ‘const’
}

正如@JonathanLeffler 指出的那样:

Chapter 8 of n3797.pdf (p180-181) shows that this is OK in the grammar rules there.

声明符列表的每个元素可以是 noptr-声明符ptr-声明符ptr-operator ptr-declarator 案例的组件有自己的 cv-qualifier-seq opt .但是 noptr-declarator 没有。

法律术语说了这么多,但为什么会这样呢?好吧,一旦我开始更多地考虑这个问题,它就有意义了:前导类型名和声明符列表之间存在明显的区别。非指针声明符创建具有该确切类型的变量,因此具有与它相同的 constness。

相比之下,指针声明符也有自己的 constness,与所引用的类型不同。而且我认为声明符列表中的每个指针都可以具有不同的 constness 的原因是由于 ptr-operator 绑定的((in)famous)方式:到变量名称,而不是引用的变量类型。

所以像这样的代码被视为 'equivalent' 非指针声明并且意味着 'all of these pointers are themselves const'...

int* const p = &i, q = &j, r = &l;

...那么语法必须完全不同,并且将 ptr-operator 视为类型名的一部分,而不是每个变量的属性。

但正如我们所知,后者才是正确的。因此,鉴于此,每个 ptr-operator 组件中 cv-qualifier-seq opt 的存在是让 one 指针有自己的 constness,与所指类型的不同。事实上,声明符列表中的每个其他指针都可以具有不同的 constness 只是其副作用,因为每个声明符都需要自己的 ptr-operator(以避免成为非指针)。

事后看来,这一切似乎都很明显。我想我今天过得很慢。