C++ typedef名称可以用于声明或定义构造函数吗? 标准语:

C++ typedef名称可以用于声明或定义构造函数吗? 标准语:,c++,language-lawyer,C++,Language Lawyer,[class.ctor]12.1/1表示 特殊的声明器语法用于声明或定义构造函数。语法使用: -可选的decl说明符seq,其中每个decl说明符都是函数说明符或constexpr -构造函数的类名,以及 -参数列表 按这个顺序 [class.name]9.1/4说 一个typedef名称(7.1.3),用于命名类类型或cv限定类型 其版本,也是一个类名。如果一个typedef名称命名一个 如果需要类名,则使用cv限定类类型 cv限定符将被忽略。typedef名称不得用作 类头中的标识符 另外[

[class.ctor]12.1/1表示

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

-可选的decl说明符seq,其中每个decl说明符都是函数说明符或constexpr

-构造函数的类名,以及

-参数列表

按这个顺序

[class.name]9.1/4说

一个typedef名称(7.1.3),用于命名类类型或cv限定类型 其版本,也是一个类名。如果一个typedef名称命名一个 如果需要类名,则使用cv限定类类型 cv限定符将被忽略。typedef名称不得用作 类头中的标识符

另外[expr.prim.general]5.1.1/8说

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


应用程序: 在我看来,应该允许使用typedef名称声明构造函数(尽管12.1/1没有使用斜体类名)

例如,假设:

struct Foo;
typedef Foo Bar;
然后

或者相反地给予

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

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

我的分析正确吗?这些编译器都错了吗?

§12.1/3州

typedef名称不得用作构造函数声明的声明器id中的类名

这排除了第(1)条

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

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


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

令人恼火的是,它似乎在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) { ... }
}.
模板
类MyTemplate{
受保护的:
typedef MyTemplate simpleName;
//声明构造函数
简单名称(int arg){…}
};
类子类
:公共MyTemplate
{
公众:
子类(int-arg):简单名称(arg){…}
}.

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

(1)似乎被§12.1/3排除(“typedef名称不得用作构造函数声明的声明器id中的类名。”)您应该澄清您所指的标准的版本,C++03(又名ISO/IEC 14882:2003)或C++11(ISO/IEC 14882:2011);我祈祷您不是指C++98。@AdamRosenield C++11,但我认为C++11在这方面没有任何改变。@AdamRosenield目前我正在查看文件N3337(2012年1月的草稿).我发现C++98的一个版本包含相同的句子,因此这似乎没有改变(与声称的相反)@barnes53:我不知道你在读什么答案,但这个答案没有提到类头,它提到了构造函数声明……你评论中的代码显然没有提到。他引用了一条与你在问题中提到的完全不同的规则。12.1p3而不是9.1p4。@BenVoigt你说得对,我浏览得太快了呃,“不得使用typedef名称”后面的文本,我不确定我是否理解为什么(2)和(3)会被这条规则所约束。哪里说“声明”同时意味着声明和定义?@bames53:在§12.1/1中,它说“一种特殊的声明符语法用于声明或定义构造函数……在这样的声明中,…”因此,我认为§12.1中“声明”一词的所有进一步使用实际上都是指这个“特殊声明者”。@ildjarn我认为这是其本意,但给出的语法(decl说明符+类名+参数列表)不匹配类外定义,因为它们包含嵌套的名称说明符而不是非限定的类名。
Foo::Bar() {}; // defines Foo's constructor - 2
Bar::Bar() {}; // defines Foo's constructor - 3
Bar::Foo() {}; // defines Foo's constructor - 4
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) { ... }
}.