4

次のコードがあります。

template<typename T, typename Allocator = std::allocator<T> >
class Carray {
    // ...
    typedef T* pointer;
    typedef pointer iterator;
    // ...
};

今、私は の部分的な特殊化をしようとしていますiterator_traits。私には問題ないように思えますが、g++ 4.4.5 は文句を言います:

#include <iterator>

namespace std {
    template<typename T, typename Allocator>
    struct iterator_traits<typename Carray<T, Allocator>::iterator> { // line 128
        typedef T value_type;
        typedef typename Allocator::difference_type difference_type;
        typedef typename Allocator::reference reference;
        typedef typename Allocator::pointer pointer;
        typedef typename std::random_access_iterator_tag iterator_category;
    };
}

これは完全なエラー メッセージです。

carray.h:128: error: template parameters not used in partial specialization:
carray.h:128: error:         ‘T’
carray.h:130: error: ‘Allocator’ has not been declared
carray.h:131: error: ‘Allocator’ has not been declared
carray.h:132: error: ‘Allocator’ has not been declared
4

1 に答える 1

10

ここでは特殊化はまったく必要ありません。 iterator_traitsすでにポインタ型に特化されており、クラス型であるイテレータができあがった場合は、それらの必要なtypedefsをイテレータクラスで定義できます。

問題は、プライマリスペシャライゼーションと一致させるために、コンパイラはテンプレートが使用される引数を取得し、それらをスペシャライゼーションにプラグインして、それらが一致するかどうかを確認する必要があることです。

次の簡略化されたシナリオで何が起こるかを考えてみましょう。

template <typename T> struct S { typedef int type; };

template <typename T> 
struct Traits { };

template <typename T> 
struct Traits<typename S<T>::type> { };

コンパイラは、何TをプラグインするSか、または一部S<T>::typeが単なるではなく本当に意味があるかどうかをどのように知ることになっていintますか?

問題は、ネストされたtypedef(::type)がテンプレートパラメータ()に依存することTです。これが関数の引数リストまたは部分的な特殊化の場合である場合、型Tを推定することはできません(これは「非推定コンテキスト」です)。

于 2011-06-18T21:24:17.037 に答える