Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial specialization fails for container iterators [duplicate]

Tags:

c++

I want to implement partial specializations for different container iterators. The code compiles fine if I do that for containers as such, but fails for their iterators:

Good

template<typename T>
struct IsContainer : std::false_type {};
template<typename T>
struct IsContainer<std::list<T>> : std::true_type {};
template<typename T>
struct IsContainer<std::set<T>> : std::true_type {};
template<typename T1, typename T2>
struct IsContainer<std::map<T1, T2>> : std::true_type {};

Produces error:

Class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used

for each specialization:

template<typename T>
struct IsIterator : std::false_type {};
template<typename T>
struct IsIterator<std::list<T>::iterator> : std::true_type {};
template<typename T>
struct IsIterator<std::set<T>::iterator> : std::true_type {};
template<typename T1, typename T2>
struct IsIterator<std::map<T1, T2>::iterator> : std::true_type {};

What is the correct form for iterators?

like image 396
Mike Lischke Avatar asked Apr 09 '19 09:04

Mike Lischke


1 Answers

The compiler message is quite descriptive here. That is the way how compiler deals with template specializations. I'll try to explain why this would be impossible to implement from the compiler's point of view.

When you have the following code:

template<typename T>
struct IsContainer : std::false_type {};
template<typename T>
struct IsContainer<std::list<T>> : std::true_type {};

when compiler needs to instantiate IsContainer<SomeType> it needs to check whether SomeType is a std::list with some template arguments or not, and this is quite doable. If yes - it uses partial specialization, if not - the generic one.

Let's try do the same for the following code:

template<typename T>
struct IsIterator : std::false_type {};
template<typename T>
struct IsIterator<typename std::list<T>::iterator> : std::true_type {};

If compiler needs to instantiate IsContainer<SomeType> it would need to check if SomeType is std::list<T>::iterator for some type T. Since list<T>::iterator is some independent type (theoretically) from list<T> the only option to do it is to enumerate all the possible types (including infinite number of template instantiations), which is obviously impossible.

like image 91
Dmitry Gordon Avatar answered Oct 14 '22 06:10

Dmitry Gordon