13

A の特殊化 S は合法であり、B の S は合法ではないのはなぜですか?

( B がコメントアウトされていない場合) GCC 4.8.1: エラー: 非名前空間スコープ 'クラス B' での明示的な特殊化</p>

#include <type_traits>
#include <iostream>

class Y {};
class X {};

struct A {
  template<class T, class = void>
  class S;

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };
};

/*
class B
{
    template<class T>
    class S;

    template<>
    class S < Y > {};

    template<>
    class S < X > {};
};
*/


int main()
{
    A::S< X > asd;
    std::cout << asd.i << std::endl;
}

on colir: B コメントアウト

on coliru: with B (エラー)

4

1 に答える 1

13

@jrok によるコメントは、コンパイラ エラーをほぼ説明しています。一般的に入れ子になったクラス、特に入れ子になったクラス テンプレートは、簡単に避けることができる言語の塵の多いコーナーです (Sutter のアドバイス「自分が知っていることを書き、自分が書いたものを知っている」を心に留めておいてください)。

namespace detailクラス テンプレートSASBその特殊化を定義する を作成し、 と のS両方Aでネストされたテンプレート タイプ エイリアスを定義するだけです。B

namespace detail {

  template<class T, class = void>
  class SA;

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };

  template<class T>
  class SB;

  template<>
  class SB < Y > {};

  template<>
  class SB < X > {};
}

struct A
{
    template<class T>
    using S = detail::SA<T>;
};

struct B
{
    template<class T>
    using S = detail::SB<T>;
};

確かに、この場合はやり過ぎに思えるかもしれませんが、テンプレート自体を作成Aしてクラス化し、 と を特化したい場合は、ネストされたクラス テンプレートを特化することができるのは、囲んでいるクラスも特化している場合のみです。要するに、コンパイル時の間接的なレベルを追加することで、これらの問題を完全に回避するだけです。BAB

于 2013-09-20T07:02:30.173 に答える