Sor*_*kfa 23 c++ language-lawyer
上周,我和一位同事讨论了cppreference.com上关于 C++ 特性文档的理解。我们查看了参数包的文档,特别是(optional)
标记的含义:
(另一个例子可以在这里找到。)
我认为这意味着这部分语法是可选的。这意味着我可以在语法中省略这部分,但始终需要编译器支持才能符合 C++ 标准。但他表示,这意味着它在标准中是可选的,编译器不需要支持这个特性来符合标准。是哪个?这两种解释对我来说都有意义。
我在 cppreference 网站上找不到任何解释。我也尝试用谷歌搜索它,但总是登陆std::optional
...
有人可以解释一下吗,也许可以发布一个链接,在哪里可以找到解释?
bol*_*lov 15
这意味着特定令牌是可选的。例如,这两个声明都有效:
template <class... Args>
void foo();
template <class...>
void bar();
Run Code Online (Sandbox Code Playgroud)
dfr*_*fri 12
在选择/ (可选)后缀表示所述符号是可选的[用于C ++程序员使用; 不是编译器支持]
由于这个问题已被标记为语言律师,并且作为一般性,当我们寻找明确的参考时,让我们从 CppReference移到标准.
CppReference 使用(可选)下标的地方,标准使用opt;例如在[temp.param]/1 中:
模板参数的语法是:
- 模板参数:
- 类型参数
- 参数声明
- 类型参数:
- 类型参数键 ... opt标识符opt
- [... 等等]
[syntax]/1描述语法符号[强调我的]:
在本文档中使用的语法符号中,语法类别用斜体表示,字面词和字符用等宽类型表示。替代方案在单独的行中列出,除非在少数情况下,一长串替代方案用短语“其中之一”标记。如果替代的文本太长而无法在一行中放置,则文本将在从第一行缩进的后续行上继续。 一个可选的终结符或非终结符由下标“ opt ”表示,所以
- { 表达式选择}
表示用大括号括起来的可选表达式。
所以,你是对的,你的同事是错的。特别是对于模板参数包的示例(我们通过可选的...
after引入typename
)identifier
之后的 after typename...
,它命名包(或模板参数,如果...
省略)是可选的。
但他表示,这意味着它在标准中是可选的,编译器不需要支持这个特性来符合标准。
如果我们使用单个类型模板参数注释类模板的“可选排列”,则这种说法的荒谬之处就变得更加明显:
template<typename>
// ^^^^^^^^ type-parameter
// (omitting optional '...' and 'identifier')
struct S;
template<typename T>
// ^^^^^^^^^^ type-parameter
// (omitting optional '...')
struct S;
template<typename...>
// ^^^^^^^^^^^ type-parameter
// (omitting optional 'identifier')
struct S;
template<typename... Ts>
// ^^^^^^^^^^^^^^ type-parameter
struct S;
Run Code Online (Sandbox Code Playgroud)
如果上述声明为真,那么只有这四个中的第一个需要由兼容实现支持(仅基于语法,在这个人为的示例中),这意味着编译器供应商可以提供我们永远无法命名的兼容实现既不是模板(类型)参数也不是函数参数。
虽然我找到了列出所有标记的页面,但我无法找到指定标记含义的页面。不过,我可能会要求你的同事看一下其他一些页面,目的是让同事放弃“可选”意味着“可选支持”的想法。(这不是一个明确的论点,但许多人会发现它很有说服力。)我在Function statements中找到了两个很好的例子。
函数声明:
noptr-declarator ( parameter-list ) cv(optional) ref(optional) except(optional) attr(optional)
重点关注cv
(“const-volatile”的缩写),它被标记为“可选”并且“仅允许在非静态成员函数声明中”。您的同事对此标记的解释意味着编译器不必支持const
成员函数,因为const
关键字是“可选的”。
函数定义,第一个选项function-body
:
ctor-initializer(optional) compound-statement
这里的“可选”部分是成员初始值设定项列表(仅在构造函数中允许)。您的同事准备好声称编译器不需要支持成员初始值设定项列表了吗?
有时,人们应该查看熟悉的注释才能理解。