5

コードを検討してください

     template <class A>
     class B;

     template <class A>
     class B<const A>{};

     template <class A, int N>
     class B<A[N]>{};

     template <class A>
     class B<A*>{};

     template <class A>
     class B<A&>{};

次のテンプレートのインスタンス化は正常に機能します。

     A<int*&>
     A<const int*>
     A<int*[3]>

しかし、次のものは機能しません:

     A<const int[3]>

この特定の組み合わせが無効である理由はありますか、それともg ++ 4.6.3のバグでしょうか?

ちなみに、SFINAEとboost :: disable_if <>を使用してこれを回避できたので、少なくとも問題は解決しました。

編集

問題のエラーはあいまいなクラステンプレートのインスタンス化であり、constのオーバーロードと配列のオーバーロードのどちらかを判断できなかったことを忘れました。

EDIT2

これはポインタとは何の関係もありません。完全なコンテキストは次のとおりです。

私は本C++Template Metaprogrammingを読み、質問2-3(第2章質問3)を実行しています。

タイプ特性機能を使用して、type_descriptorクラステンプレートを実装します。このテンプレートのインスタンスは、ストリーミングされると、テンプレートパラメータのタイプを出力します。注:18.5.1 [lib.type.info]によると、同じ効果でRTTIを使用することはできません。標準のパラグラフ7、typeid(T).name()は、意味のある結果を返すことが保証されていません。

私の解決策(コンパイルエラーの回避策を含む)は次のとおりです。

    //QUESTION 2-3
    template <class T, class enable = void>
    struct type_descriptor
    {
      std::string operator()() const
      {
        return "Unknown";
      }
    };

    //specializations for primitive types
    #define TYPE_DESC_SPEC(type) template <>    \
      struct type_descriptor<type,void>     \
      {std::string operator()() const{return #type;}};

    TYPE_DESC_SPEC(int)
    TYPE_DESC_SPEC(long)
    TYPE_DESC_SPEC(void)
    TYPE_DESC_SPEC(short)
    TYPE_DESC_SPEC(unsigned char)
    TYPE_DESC_SPEC(unsigned short)
    TYPE_DESC_SPEC(unsigned long)

    //specializations for modifiers *, const, &, and [N]

    template <class T>
    struct type_descriptor<T&,void>
    {std::string operator()(){return type_descriptor<T>()() + " &";}};

    template <class T>
    struct type_descriptor<T*,void>
    {std::string operator()(){return type_descriptor<T>()() + " *";}};

    //Replace void with what's in the comment for the workaround.
    template <class T>
    struct type_descriptor<const T, void/*typename boost::disable_if<boost::is_array<T> >::type*/>
    {std::string operator()(){return type_descriptor<T>()() + " const";}};

    template <class T>
    struct type_descriptor<T(*)(),void>
    {std::string operator()(){return type_descriptor<T>()() + " (*)()";}};

    template <class T, class U>
    struct type_descriptor<T(*)(U),void>
    {std::string operator()(){return type_descriptor<T>()() + " (*)(" + type_descriptor<U>()() + ")";}};

    template <class T, int N>
    struct type_descriptor<T[N],void>
    {
      std::string operator()()
      {
        std::stringstream s;
        s << type_descriptor<T>()() << " [" << N << "]";
        return s.str();
      }
    };

    template <class T>
    struct type_descriptor<T[],void>
    {std::string operator()(){return type_descriptor<T>()() + " []";}};

    //Now overload operator<< to allow streaming of this class directly

    template <class T>
    std::ostream & operator<<(std::ostream & s, type_descriptor<T> t)
    {
      return s << t();
    }
    //END QUESTION 2-3

使用例は次のとおりです。

      std::cout << "\nQuestion 2-3 results\n";
      std::cout << type_descriptor<int*>() << std::endl;
      std::cout << type_descriptor<int*[3]>() << std::endl;
      std::cout << type_descriptor<std::string*>() << std::endl;
      std::cout << type_descriptor<const int&>() << std::endl;
      std::cout << type_descriptor<const int *const&>() << std::endl;
      std::cout << type_descriptor<int[4]>() << std::endl;
      std::cout << type_descriptor<int(*)()>() << std::endl;
      std::cout << type_descriptor<int*&(*)(const char &)>() << std::endl;
      std::cout << type_descriptor<int*&>() << std::endl;
      std::cout << type_descriptor<int[]>() << std::endl;
      std::cout << type_descriptor<const long[]>() << std::endl;

対応する出力は次のとおりです(回避策が実行されている場合、それ以外の場合は最後の出力でコンパイルされません)。

int *

int * [3]

わからない *

int const&

int const * const&

int [4]

int(*)()

int *&(*)(不明なconst&)

int *&

int []

long const []

したがって、C ++は、テンプレートパラメータのポインタと配列を区別し、複合型を正しく、再帰的に分離し、を除いて正しい結果を出力することができますconst A[]。それはそれで助けが必要です

4

1 に答える 1

1

const要素型の配列型は、const修飾型(constは双方向に適用されます)と配列型の両方です。

したがって、専門分野を修正する必要があります。

于 2012-10-17T09:00:37.843 に答える