2013-03-15 15 views
14

CRTPがテンプレート内で使用される場合(または一般にテンプレートパラメータが基本クラステンプレート引数として渡される場合)、using宣言でベースのメンバテンプレートに名前を付けることはできませんか?型依存テンプレート名の宣言の使用

template< typename d > 
struct base { 
    template<typename> 
    struct ct {}; 

    template<typename> 
    void ft() {} 
}; 

template< typename x > 
struct derived : base< derived<x> > { 
    using derived::base::template ct; // doesn't work 
    using derived::base::ft; // works but can't be used in a template-id 
}; 

using宣言文法の生産は資格-IDを内蔵していないという理由だけで、言語の穴であるように私には思えます。

using-declaration: 
    using typename(opt) nested-name-specifier unqualified-id ; // have this 
    using :: unqualified-id ; 

unqualified-id: 
    identifier 
    operator-function-id 
    conversion-function-id 
    literal-operator-id 
    ~ class-name 
    ~ decltype-specifier 
    template-id 

qualified-id: 
    nested-name-specifier template(opt) unqualified-id // want this 
    :: identifier 
    :: operator-function-id 
    :: literal-operator-id 
    :: template-id 

だけルールがusing-declaration: using typename(opt) qualified-idた場合は、唯一の結果は

  • :: ~ class-name:: conversion-function-idを除外されるだろう、と何の意味論的な意味を成さない:: ~ decltype-specifier template-id
  • が既に明示により禁止されている:: template-idを許可します7.3.3/5、および
  • この穴にパッチを当てるのに十分な仕様を既に持っているtemplateキーワードを許可します。

この分析は正しいですか?

typenameの宣言では、クラステンプレートまたはエイリアステンプレートをインポートする必要があり、typenameを含まない宣言では、関数または変数テンプレートを現在のスコープにインポートする必要があります。

 using typename derived::base::template ct; 
    using derived::base::ft; 

これには、追加の仕様が必要な場合があります。また、現在の現状は、依存するテンプレート名には常に曖昧な種類(テンプレートIDではない)があるため、typenamectに属していることは明らかではありません。

+0

興味深い分析です。特定された「穴」が抑止されるような方法で*これを使用する場所が不思議です。私。これがプログラムのアーキテクチャを取り返して再検討しなければならないロードブロッキングである現実のアプリケーションとは何ですか? – WhozCraig

+0

@WhozCraigこれは、テンプレートからCRTPを使用するたびに表示されます。基本クラスは、使用するたびに 'this - > * template'または' base :: template'と言うべきインタフェースを提供します。 – Potatoswatter

+0

さて、私はそれを得ると思います。この特殊なケースは、 'using'節でそれを使って人生を楽にすることですが、許可されていないようです。良い例え。ありがとうございました。 – WhozCraig

答えて

2

次はC++ 11で正常に動作します:

#include <iostream> 

template< typename d > 
struct base { 
    template<typename> 
    struct ct {}; 

    template<typename> 
    void ft() {std::cerr << "cheesecake" << std::endl;} 
}; 

template< typename x > 
struct derived : base< derived<x> > { 
    template<typename X> 
    using ct = typename derived::base::template ct<X>; // new in C++11 
    using derived::base::ft; 
}; 

int main() 
{ 
    derived<int>::ct<float> c; 
    derived<int> a; 
    a.ft<int>(); 
} 

それはあなたが望んでいない場合は、あなたがCTフィートを使用したいと思う方法の例をお願いできますか?

+1

ええ、テンプレートエイリアスは動作しますが、関心事の分離をやや壊すテンプレート署名を再宣言する必要があります。関数 'using'宣言は' derived'のスコープ内では機能しません。完璧な転送が機能します。しかし、これらは宣言を使用していません。追加されたフットワークは、ある宣言を新しい宣言なしで1つのスコープから関連するものにインポートする、 'using'宣言の目的に反するものです。とにかく...完璧な転送を追加し、私はこれを受け入れる必要があります。 – Potatoswatter

関連する問題