10

別のテンプレート内にネストされたクラス テンプレートがあります。部分的に特殊化するのは簡単ですtemplate< … >。親の中で別のブロックを宣言するだけです。

ただし、すべてのローカル テンプレート引数を指定する別の部分的な特殊化が必要です。これにより、明示的な特殊化になります。明示的な特殊化は、何らかの理由で、名前空間のスコープにある必要があります。親クラスの外で宣言するには、親を指定する必要があります。これには、空でないテンプレート引数リストが必要です。これは、部分的な特殊化を意味します。私が行っているの部分的な特殊化であり、任意の外側のスコープで動作するはずです。しかし、GCC と Comeau はどちらも、部分特殊化の仮引数を使用して、親の指定でテンプレート パラメーターを識別できません。

template< class X > struct A {
    template< class Y > struct B; // initial declaration OK

    template< class Z >
    struct B< A< Z > > {}; // partial OK as long as there's a local arg

    template<> // ERROR: this syntax triggers explicit specialization
    struct B< int > {};
};

template<> // ERROR: can't nest template<>s here (why?)
template< class X > // ERROR: can't deduce X from type of A<X>::B<int> (why?)
struct A< X >::B< int > {};

(動作しないコードはすべて残しました。意味を理解するために適切にコメントしてください。)

4

4 に答える 4

9

C++ 標準 14.7.3/18 では違法です。

.... 宣言は、それを囲むクラス テンプレートも明示的に特殊化されていない場合、クラス メンバー テンプレートを明示的に特殊化してはなりません。

于 2010-01-06T12:41:47.383 に答える
4

ネストされたクラスをあまり使用しない傾向があります。私の主な不満は、ネストされているクラスのコードを肥大化させる傾向があることです。

したがって、別の回避策を提案します。

namespace detail
{
  template <class X, class Z> class BImpl;
  template <class X, class Z> class BImpl<X, A<Z> > {};
  template <class X> class BImpl<X,int> {};
}

template <class X>
class A
{
  template <class Z> struct B: BImpl<X,Z> {};
};

BImpl特殊化も行いたい場合は、 X を引数として渡す必要があることに注意してくださいA。面白いことに、この場合、部分的な専門化しかできません!

于 2010-01-06T18:11:17.240 に答える
0

複雑なもの。あなたの最初のコードICEのVC10Beta2、いいですね。

まず、あなたはこれを逆に持っていると思います:

template<> 
template< class X > 
struct A< X >::B< int > {};

Xは構造体Aのテンプレートパラメータであり、Bは完​​全に特殊化されたものなので、次のようになります。

template< class X > 
template<> 
struct A< X >::B< int > {};

しかし、これでもコンパイルに失敗します。ただし、エラーテキストは実際には役立ちます。

a.cpp a.cpp(11):エラーC3212:'A :: B':テンプレートメンバーの明示的な特殊化は、明示的な特殊化のメンバーである必要がありますa.cpp(8):' A::Bの宣言を参照してください'

Aも完全に専門化する場合にのみ、Bを完全に専門化することが合法であるように見えます。

編集:わかりました、これについて権威を持って話すことができる誰かから返事がありました-言い換えると、これは標準の非常に曖昧な領域であり、それをクリーンアップすることはC ++委員会の未解決の問題です(「それ」は明示的な専門分野ですクラステンプレートのメンバー)。短期的には、アドバイスは「そうしないでください」です。

于 2010-01-06T00:29:31.777 に答える
0

少なくともこれはVC2010で機能します。しかし、私はdefを書くことができません。クラス宣言外の「int」のfun()の。編集:残念ながら、g++にはコンパイルの問題もあります。編集:以下のコードはVC2010で機能しました。

template<typename X>
class A
{
public:
    A()
    {

    }

    template<typename Y>
    struct B
    {
        void fun();
    };

    template<>
    struct B<int>
    {
        void fun()
        {
            cout << "Specialized version called\n";
        }
        //void fun();
    };



public:

    B<X> b;
};



template<typename X>
template<typename Y>
void A<X>::B<Y>::fun()
{
    cout << "templated version called\n";
}

int main()
{
   A<int> a;
    a.b.fun();
    A<float> a1;
    a1.b.fun();
}
于 2010-01-06T01:09:08.567 に答える