Reputation: 10895
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
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