【问题标题】:Can typedef names be used to declare or define constructors?typedef 名称可以用于声明或定义构造函数吗?
【发布时间】:2012-07-13 22:03:20
【问题描述】:

标准:

[class.ctor] 12.1/1 说

一种特殊的声明符语法用于声明或定义构造函数。语法使用:

     - 一个可选的 decl-specifier-seq,其中每个 decl-specifierfunction-specifierconstexpr,

    - 构造函数的类名,以及

    ——一个参数列表

按这个顺序。

[class.name] 9.1/4 说

一个 typedef-name (7.1.3) 命名一个类类型,或一个 cv 限定 其版本,也是一个类名。如果一个 typedef-name 命名一个 在需要 class-name 的地方使用 cv 限定的类类型, cv 限定符被忽略。 typedef-name 不得用作 类头中的标识符

还有 [expr.prim.general] 5.1.1/8 说

其中class-name :: class-name使用,两个class-name是指 对于同一个类,这个符号命名构造函数(12.1)。


应用:

在我看来,这似乎是说应该允许使用 typedef 名称声明构造函数(尽管 12.1/1 不使用斜体 class-name)。

例如,给定:

struct Foo;
typedef Foo Bar;

然后

struct Foo { Bar() {} }; // defines Foo's constructor. - 1

或者改为给定

struct Foo;
struct Foo { Foo() };
typedef Foo Bar;

然后

Foo::Bar() {}; // defines Foo's constructor - 2

Bar::Bar() {}; // defines Foo's constructor - 3

Bar::Foo() {}; // defines Foo's constructor - 4

任何这些都应该是合法的。但是似乎没有人接受定义 2 或 3,MSVC 接受 1,MSVC、clang 和 gcc 都接受 4。

我的分析是否正确,所有这些编译器都错了吗?

【问题讨论】:

  • (1) 似乎被 §12.1/3 排除(“A typedef-name 不应用作构造函数声明的 declarator-id 中的类名。”)跨度>
  • 您应该澄清您所指的标准的哪个版本,C++03(又名 ISO/IEC 14882:2003)或 C++11(ISO/IEC 14882:2011);我祈祷你不是指 C++98。
  • @AdamRosenfield C++11,但我不认为 C++11 在这方面有任何改变。
  • @AdamRosenfield 目前我正在查看文档 N3337(2012 年 1 月的草稿)。我找到了包含相同句子的 C++98 版本,所以这似乎没有改变(与 amalp.blogspot.de/2007/07/typedef-name-as-identifier-of.html 声称的相反)。

标签: c++ language-lawyer


【解决方案1】:

the working draft N3337 (Feb 2012) 州的§12.1/3

typedef-name 不得用作构造函数声明的 declarator-id 中的 class-name

这排除了(1)。

§12.1/1 似乎对声明和定义都使用了“声明”一词:

一种特殊的声明符语法用于声明或定义构造函数。 […] 在这样的声明中,[…]

(没有明确提到“定义”)。我认为这是否适用于类外定义或仅适用于内联定义有点不清楚。如果它适用于所有类型的定义,这也将排除(2)和(3)。 (4) 在任何情况下都应该是合法的。

【讨论】:

  • @barnes53:我不知道你在读什么答案,但是这个没有提到 class-head,它确实提到了构造函数声明。 . 您评论中的代码显然不是。他引用了与您在问题中提到的完全不同的规则。 12.1p3 而不是 9.1p4。
  • @BenVoigt 你说得对,我在“A typedef-name 不得使用”之后的文字上浏览得太快了
  • 我不确定我是否理解为什么 (2) 和 (3) 受此支配。哪里说“声明”既是声明又是定义?
  • @bames53 :在 §12.1/1 中它说“一种特殊的声明符语法用于声明或定义构造函数。......在这样的声明中,...... " 所以我认为 §12.1 中“声明”一词的所有进一步使用实际上都是指这个“特殊声明符”。
  • @ildjarn 我认为这是预期的含义,但是呈现的语法(decl-specifiers + class name + parameter list)与类外定义不匹配,因为它们包含嵌套的名称说明符而不是不合格的类名。
【解决方案2】:

很烦人,它似乎在 Microsoft C 中有效,但在我使用的其他编译器中无效。 特别是在模板中需要时。也许我不知道这样做的“标准兼容方式”,但它在模板中真的很有用。

template<class T, class T1, ... /* messy, verbose */ >
class MyTemplate {
protected:
    typedef MyTemplate<T,T1, ... /* messy, verbose */ > SimplerName;

    // declare a constructor
    SimplerName(int arg) { ... }
};
class SubClass
    : public MyTemplate<x,y....>
{
public:
    SubClass(int arg) : SimplerName(arg) { ... }
}.

也许是另一个问题,这在 GCC、Clang 等中不起作用,有没有办法在其他编译器中做到这一点?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2014-01-17
    相关资源
    最近更新 更多