標準:
[class.ctor] 12.1/1は言う
コンストラクターを宣言または定義するには、特別な宣言子構文が使用されます。構文は以下を使用します:
—オプションのdecl-specifier-seq。各decl-specifierはfunction-specifierまたはconstexprのいずれかです。
—コンストラクターのクラス名、および
—パラメータリスト
その順序で。
[class.name] 9.1/4は言う
クラスタイプまたはそのcv修飾バージョンを指定するtypedef-name(7.1.3)も、クラス名です。クラス名が必要な場所でcv修飾クラスタイプを指定するtypedef-nameが使用される場合、cv修飾子は無視されます。typedef-nameは、クラスヘッドの識別子として使用してはなりません 。
また、[expr.prim.general] 5.1.1/8は言います
class-name :: class-nameが使用され、2つのclass-nameが同じクラスを参照する場合、この表記はコンストラクター(12.1)に名前を付けます。
応用:
これは、コンストラクターの宣言はtypedef名を使用して許可する必要があると私には思えます(12.1 / 1はイタリック体のクラス名を使用しないという事実にもかかわらず)。
たとえば、次のようになります。
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を受け入れます。
私の分析は正しいですか、そしてこれらのコンパイラはすべて間違っていますか?