15

標準:

[class.ctor] 12.1/1は言う

コンストラクターを宣言または定義するには、特別な宣言子構文が使用されます。構文は以下を使用します:

    —オプションのdecl-specifier-seq。各decl-specifierfunction-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を受け入れます。

私の分析は正しいですか、そしてこれらのコンパイラはすべて間違っていますか?

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 に答える