15

标准语:

[class.ctor] 12.1/1 说

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

    — 一个可选的decl-specifier-seq,其中每个decl-specifier函数说明符constexpr

    — 构造函数的类名,以及

    — 参数列表

以该顺序。

[class.name] 9.1/4 说

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

[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。

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

4

2 回答 2

14

工作草案 N3337(2012 年 2 月)第12.1/3 条规定

typedef-name不应用作构造函数声明的declarator-id中的类名。

这排除了(1)。

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

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

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

于 2012-07-13T22:15:21.527 回答
0

令人讨厌的是,它似乎在 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 等中不起作用,有没有办法在其他编译器中做到这一点?

于 2018-12-09T07:29:06.220 回答