2011-09-12 11 views
23

継承するコンストラクタはC++のテンプレートで動作しますか0xですか?

C++ 0xでは、次のように usingキーワードを使用してコンストラクタを継承できます。

class B { B(int) {} }; 

class A : public B { using B::B; }; 

暗黙のうちにA(int)コンストラクタを宣言します。これはテンプレートで動作しますか?

class B { B(int) {} }; 

template<class T> class A : public T { using T::T; }; 

T::Tでは、テンプレート引数にスコープ演算子を使うのは普通ですが、右手のTはコンストラクタであることが分かりますから、コンパイラは左手Tを計算することを期待しています。実際にはあいまいさがあるようです:BというメソッドがBというメソッドを持っていて、Aにオーバーロードを追加しようとしているのですが(これはコンパイラがpre-C++ 0xのような宣言を解釈する方法です)?

答えて

10

はい、動作します。その理由は名前検索メカニズムです。継承コンストラクタ宣言の仕組みは簡単です:使用宣言の名前が基本クラスコンストラクタを参照する場合、それは継承コンストラクタ宣言です。 3.4.3.1で[class.qual] P2我々は見つける:コンストラクタが許容検索結果であり、場合、ネストされた名指定子は、クラスC

  • を指名したルックアップで

    をネストされた名前の後に指定された名前は、Cで検索されたとき、Cの注入クラス名(第9項)、またはメンバー宣言である使用宣言(7.3.3)の

  • ネストされた名前指定子の後に指定された名前が、ネストされた名前指定子の最後のコンポーネントの識別子または単純テンプレートIDのテンプレート名と同じ場合

名が代わりにC.

クラスのコンストラクタに名前を付けるために考えられている

このクラスのコンストラクタの定義の外になり段落は仕事、そしてこれはまた、コンストラクタ宣言の仕事を継承しますパラグラフです。第二弾は、この場合に適用される:

struct B { 
    B(int) { } 
}; 

typedef B mytype; 

struct A : B { 
    // "name ... is the same as the identifier ... in the last component ..." 
    using mytype::mytype; 
}; 


template<typename T> using same = T; 

struct C : B { 
    // "name ... is the same as the template-name ... in the last component ..." 
    same<B>::same; 
}; 

後者の例は、要するに以下

template<template<typename> class Base> 
struct X : Base<int> { 
    using Base<int>::Base; 
}; 

ような場合にも役立ち:

  • 上記第一弾は、Aであります意味規則 - ネストされた名前指定子の後の名前が注入されたクラス名(B::Bまたはmytype::B)を参照する場合、それは構造体を参照するように翻訳されますまたは(s)。

  • 第二弾が構文規則である - その意味は、それ以外の場合は無関係です - - 名前がちょうど一致している必要がありますメンバーは、以下のように、Xに提供されるテンプレート引数にBaseと呼ばれるがあったかもしれないが、使用して宣言はまだコンストラクタをインポートし、ない名にメンバーBaseだろう:型名T 'は、それがタイプ記号のプレースホルダを表しという名前のメソッドTを表すものではありません `ので、大丈夫だと思う

    template<typename T> struct D { private: T Base; }; 
    X<D> x; // valid, the private member is *not* touched! 
    
7

はい、セクション12.9、標準(2011年2月ドラフト)から、それがない表示されます。メッセージを書き込み中Dは任意のクラスをラップし、転送し、そのすべてのコンストラクタの、

template< class T > 
struct D : T { 
using T::T; // declares all constructors from class T 
~D() { std::clog << "Destroying wrapper" << std::endl; } 
}; 

クラステンプレート クラスDのオブジェクトが破棄されるたびに標準ログに出力します。 -end example

this listによると、標準では許可されているが、1つのコンパイラであるIBM XLC++のみがリリース版でこの機能をサポートしています。 GCCは現在、パッチでそれをサポートしています。

編集:AJG85は、テンプレートのTは常にプレースホルダを参照するため、 'T :: T'を使用すると常にテンプレート引数を参照すると指摘しました。

+1

いいえによって使われたテンプレートのインスタンス化。たとえば、 'A 'は 'int :: int;'を使用します:警告の言葉:STLコンテナのような基本クラスではない型の場合はどうなりますか? – AJG85

+0

あなたはメンバー変数の質問で正しいです。 STLコンテナの継承に関しては動作しますが、多態性の型で型を使用する場合は危険です。しかし、単純にD >を作成し、それを1か所のように使用すると、うまくいきます。それは良い習慣ではありませんが、機能するでしょう。 –

+0

正しいですが、派生オブジェクトに状態を追加するか、ベースクラスポインタを使用すると、後で問題の継承と根本原因が多少わかりにくくテンプレートとして導入される可能性があります。 – AJG85

関連する問題