1

この質問は、gcc のバグ レポート (gcc 4.5.0 で修正されたと思われる) が言及された以前の Q&Aに関連しており、ネストされたクラス テンプレートの部分的な特殊化に関するいくつかの特殊性に関係しています。

私のセットアップは、部分的に特化Baseされたネストされたクラス テンプレートを持つクラスがあることです(クラス内で明示的な仕様が許可されていないため、ダミー パラメーター トリックを使用します)。Innerchar

#include <type_traits>
#include <iostream>
#include <ios>

struct Base
{
    // dummy template parameter...
    template<class U, class _ = void> struct Inner: std::true_type {};

    // ... to allow in-class partial specialization
    template<class _> struct Inner<char, _>: std::false_type {};
};

Derivedここで、さらに特化したいクラスを定義しますがInner、これは何らかの奇妙な理由でクラス内で行うことができません (まだ部分的な特化であるにもかかわらず)。

struct Derived
:
    Base
{
    // cannot partially specialize Inner inside Derived...
    //template<class _>
    //struct Inner<int, _>: std::false_type {};
};

// ... but specializing Derived::Inner at namespace scope, also specializes it for Base::Inner
template<class _> struct Derived::Inner<int, _>: std::false_type {};

最初の質問Derived::Inner:名前空間スコープで部分的に特殊化する必要があるのはなぜですか?

しかし、最も奇妙な部分は、 と のInner両方のさまざまな部分特殊化を呼び出すBaseと、に対してのみ行っDerivedた部分特殊化がにも適用されることです。intDerivedBase

int main()
{
    std::cout << std::boolalpha << Base::Inner<float>::value << "\n";    
    std::cout << std::boolalpha << Derived::Inner<float>::value << "\n";    

    std::cout << std::boolalpha << Base::Inner<char>::value << "\n";    
    std::cout << std::boolalpha << Derived::Inner<char>::value << "\n";    

    std::cout << std::boolalpha << Base::Inner<int>::value << "\n";      // huh???
    std::cout << std::boolalpha << Derived::Inner<int>::value << "\n";   // OK 
}

2 番目の質問: 部分的にしか特殊化されていないのに、なぜ が にBase::Inner<int>::value等しいのですか?falseDerived::Inner<int>

gcc 4.8.0 を使用したオンラインの例。この動作を説明する標準からの引用を特に探しています。

4

2 に答える 2

1

部分的な特殊化では、代替定義を提供するプライマリ テンプレートと同じ名前を再宣言する必要があります。

struct Innerのスコープ内で記述する場合Derivedは、 を宣言してDerived::Innerいます。Base::Innerとは異なる名前Derived::Innerであるため、別のクラスを宣言します。Base::Innerを宣言する宣言で特殊化することはできませんDerived::Inner

名前空間スコープで記述Derived::Innerすると、名前のルックアップによってその名前が解決されますBase::Inner。特殊化はすべて同じ class:Base::Innerとして参照されますDerived::Inner

標準から:

[temp.class.spec]

クラス テンプレートの部分的な特殊化は、特殊化の引数が部分的な特殊化で指定された引数と一致する場合に、プライマリ定義の代わりに使用されるテンプレートの代替定義を提供します。

于 2013-06-17T18:56:37.133 に答える
1

テンプレートの特殊化は、ポリモーフィズムの一部ではありません。

あなたは実際に型を宣言しています。したがって、テンプレートの特殊化の実装を含む派生ヘッダー ファイルを参照できるコンパイル ユニットは、ネストされたテンプレート クラスにその特殊化を使用します。

コンパイラは最適なクラスを見つけようとし、常にデフォルトよりも特化された型を選択します。したがって、基本型のスコープにアクセスしようとしても、それは同じクラスのままです。

コードの他の部分でテンプレート クラスを特殊化すると、同じことが起こります。コンパイラは、最適な特殊化を選択します。ない場合は、「デフォルト」が使用されます。

于 2013-06-16T11:28:25.770 に答える