gpt4 book ai didi

c++ - 为什么转换函数声明不需要至少一个define-type-specifier

转载 作者:行者123 更新时间:2023-12-02 09:53:18 29 4
gpt4 key购买 nike

Except in a declaration of a constructor, destructor, or conversion function, at least one defining-type-specifier that is not a cv-qualifier shall appear in a complete type-specifier-seq or a complete decl-specifier-seq.


构造函数是一个异常(exception),因为构造函数可以像 constructor(){}一样声明,该声明中没有define-type-specifier,与析构函数类似。
对于 conversion function,当我在上述引用中认为 defining-type-specifier包含 type-specifier时,我不知道转换函数不需要类型说明符,因为句子 define-type-specifier不是cv限定词意味着,只有 类型说明符包含cv-qualifier,因此,我认为转换函数声明应至少包含一个 定义类型说明符(在较小范围内,它是类型定义符,它是define-type的子集-specifier),由于 [dcl.fct.def#general-1],转换函数的语法如下所示:

attribute-specifier-seq(opt) decl-specifier-seq(opt) declarator virt-specifier-seq(opt) function-body


因此,其声明者将如下所示:

operator conversion-type-id

conversion-type-id

type-specifier-seq conversion-declarator(opt)



但是根据 [class.conv.fct],它说:

A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall be neither a defining-type-specifier nor static.


这意味着 decl-specifier-seq(opt)不能是定义类型说明符,也不能是静态的。
但是,在转换类型ID的类型说明符序列中,它必须是定义类型说明符。
operator Type(){  // Type is a defining-type-specifier(more exactly,it's a type-specifier)
return Type{};
}
并且您不会定义这样的转换函数:
operator (){ // there's no defining-type-specifier in type-specifier-seq
//...
}
[dcl.fct#11]

Types shall not be defined in return or parameter types.


这是因为定义类型说明符必须出现在函数声明中的限制,由于
定义类型说明符包括:
  • type-specifier
  • class-specifier
  • enum-specifier

由于最后一个引号,不能在函数delcaration的decl-specifier-seq中使用 class-specifierenum-specifier。只允许使用 type-specifier
因此,到目前为止,该标准实际上要说的是,对 类型说明符使用更多范围的措辞,即 定义类型说明符,因为您确实可以声明一个像 struct A{} variable;这样的变量,类型说明符中不包含 类说明符,因此,作为一般规则,标准使用“措辞” 定义类型说明符来涵盖此类情况。
那么,为什么转换函数是第一条规则中的异常(exception)?如果以上分析中有任何误解,请纠正我。
问题:
  • 为什么转换函数是第一个引号中的异常?
  • 如果转换函数是一个异常(exception),为什么其他函数也不异常(exception)?
  • 最佳答案

    我同意-段落[dcl.type]/3应该改为:

    Except in a declaration of a constructor, destructor, or conversion function, or in a lambda-declarator, a complete decl-specifier-seq shall contain at least one defining-type-specifier that is not a cv-qualifier. A complete type-specifier-seq shall contain at least one type-specifier that is not a cv-qualifier.


    您是正确的:
  • 定义类型说明符比类型说明符解析更广泛的输入 token 序列集。
  • decl-type-specifier解析的输入 token 序列集比define-type-specifier还要宽。
  • constvolatile在解析这三个中的任何一个时都是有效的。
  • 包括class ClassName { ... };enum EnumName { ... };的语法在define-type-specifier或decl-type-specifier中有效,但在type-specifier中无效。

  • C++ grammar在许多需要输入类型名称的地方使用type-specifier-seq和decl-specifier-seq(加上一些不使用类型命名的地方)。在这些序列中,带引号的 [dcl.type]/3段落要求“至少一个不是cv限定词的define-type-specifier”主要是说在所有这些情况下,不允许根本不命名类型的变体:您不能说 auto v1 = new const;static constexpr typedef f();。大多数个人用途对哪种类型的指定符可以出现在此处或不能出现在那里有附加的限制,但是这些规则是对这一基本规则的补充。特别是,其中许多不允许在说明符序列中定义类型。但是,由于在简单声明中使用了decl-type-specifier作为定义类和枚举的常规方法,因此该规则并不是该限制的地方。
    排除构造函数,析构函数和转换函数的原因是,尽管它们可能根本没有decl-type-specifier-seq,但实际上它们可能使用不包含任何定义类型-specifier的decl-type-specifier 。例如,在
    class MyClass {
    public:
    explicit MyClass(int);
    };
    构造函数声明中有一个decl-type-specifier,其唯一的说明符是 explicit关键字,它不是define-type-specifier。
    (但是,在浏览过程中,我发现了另一个不适用于该规则的上下文:lambda表达式在其参数列表后允许一个可选的decl-specifier-seq,其中唯一允许的说明符为 mutableconstexpr;这两个都不是定义类型-说明符。)
    我猜想此段落版本是在C++ 14和C++ 17之间的语法中出现的或随之而来的。简单声明中的初始decl-specifier-seq已从可选更改为必需。添加了新的语法符号nodeclspec-function-declaration,以涵盖与好友声明和模板相关的声明的情况,这些声明声明了没有初始说明符且未定义它们的构造函数,析构函数或转换函数。构造函数,析构函数和转换函数的其他声明实际上都由function-definition或member-declaration覆盖,它们仍使用可选的decl-specifier-seq,因此对简单声明的更改不会影响它们。
    对于转换功能, [class.conv.fct]/1中的文字说

    A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall be neither a defining-type-specifier nor static.


    形成实际需求:[dcl.type]语句从其通常需求中排除了转换函数的decl-type-specifier-seq,因此它没有说明什么是合法的。这个[class.conv.fct]句子给出了这种情况的实际规则。
    可以声明一个转换函数:
  • 通过功能定义(如果它具有主体,包括=default;=delete;)
  • 通过成员声明(在类定义内,如果声明没有主体)
  • 通过简单声明或nodeclspec-function-declaration(如果在 friend 声明中,显式特化或显式实例化中)

  • nodeclspec-function-declaration不允许使用任何初始说明符,但其他三个符号都有一条规则,其中decl-specifier-seq(必需或可选)后跟声明符或init-declarator-list。如您所述,转换函数的声明符包含 operator关键字,后跟一个type-specifier-seq。声明程序还必须包含 ()(void)或等效文件,以便声明不带参数的函数。
    再有一些假设,转换函数声明的一般形式是

    attribute-specifier-seqopt decl-specifier-seqopt operator type-specifier-seq conversion-declaratoropt attribute-specifier-seqopt parameters-and-qualifiers virt-specifier-seqopt pure-specifieropt ;


    要么

    attribute-specifier-seqopt decl-specifier-seqopt operator type-specifier-seq conversion-declaratoropt attribute-specifier-seqopt parameters-and-qualifiers virt-specifier-seqopt function-body


    因此,在 operator关键字之前有一个可选的decl-specifier-seq,在其后有一个必需的type-specifier-seq。它是decl-specifier-seq,可能根本不存在,并且绝对不能包含define-type-specifier(因为您没有在 operator关键字之前输入类型)或 static(因为转换函数必须始终为非静态成员)。但是decl-specifier-seq可能包含 constexprinlinevirtualexplicit或它们的组合。
    您已经注意到的麻烦是[dcl.type] / 3的措词在技术上也不适用于此类声明中的type-specifier-seq,该声明为转换指定了目标类型。 ( [dcl.pre]/4清除了声明中有关语法符号的许多类似语句,但由于不涉及中间范围,因此不适用于这种情况。)我们仍然可以从标准中的短语中推断出需要一个define-type-specifier,例如“由conversion-type-id指定的类型”。但是如果[dcl.type] / 3中的规则像对大多数其他类型一样适用于此type-specifier-seq,那会更好。

    关于c++ - 为什么转换函数声明不需要至少一个define-type-specifier,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62506440/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com