Christian Ivicevic
Christian Ivicevic

Reputation: 10895

Compiler rejects two identical template specializations

I am using two helper structs to work with smart pointers and vectors

template<typename T>
struct Pointer {
    typedef shared_ptr<T> type;
};

template<typename T>
struct Vector {
    typedef vector<T, allocator<T>> type;
};

in this case is is obvious that the expression

is_same<
    vector<
        shared_ptr<T>,
        allocator<shared_ptr<T>>>,
    Vector<
        Pointer<T>::type>::type>
::value

yields true. However I have now a templated function (in fact an oparator) which is handled differently when using Vector<Pointer<T>::type>::type or the usual vector:

// (1) General version
template<typename T>
Foo& operator&(T& object);

// (2a) Specialized version
template<typename T>
Foo& operator&(vector<shared_ptr<T>, allocator<shared_ptr<T>>>& object);

// (2b) Specialized version which does not work
template<typename T>
Foo& operator&(typename Vector<typename Pointer<T>::type>::type& object);

Calling this operator when having (2a) in my code works as expected. However when I replace (2a) with (2b) then the compiler/linker tries to match the call with (1) which yields a link error for me as (1) is not defined/valid for vectors. Why is the compiler treating (2a) and (2b) differently?

Upvotes: 1

Views: 139

Answers (1)

Daniel Frey
Daniel Frey

Reputation: 56863

Because the compiler is unable to deduce the type in (2b). The problem is that it can match against

vector<shared_ptr<T>,allocator<shared_ptr<T>>>

because that is "just a type" to match against. For any given parameter, it just checks if there is a T and the type matches. There is only one option which the compiler has to test. For

typename Vector<typename Pointer<T>::type>::type

the compiler would have to try all T for with Vector<...>::type would yield to required type, which it does not do. That analysis, if at all possible, would be way more complex than just matching the direct type.

Upvotes: 5

Related Questions