Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specialize Iterator by its value type, in C++?

Is it possible to specialize an Iterator template parameter by its value_type?

I have a function with the following prototype.

template<typename InputIterator>
void f(InputIterator first, InputIterator last);

And I want to handle specially if InputIterator::value_type is SomeSpecificType.

like image 661
niboshi Avatar asked Jun 08 '11 03:06

niboshi


People also ask

What is iterator traits?

iterator_traits are used within algorithms to create local variables of either the type pointed to by the iterator or of the iterator's distance type. The traits also improve the efficiency of algorithms by making use of knowledge about basic iterator categories provided by the iterator_category member.


2 Answers

You can use some intermediate structs to get the partial template specialisation that you need. Something like this should do the trick

template<typename T, typename V>
struct f_impl
{
  static void f( T first, T last ) {...}; //Default version
};

template<typename T>
struct f_impl<T, SomeSpecificType>
{
   static void f(T first,T last) {...}; //Specialisation
};

template<typename InputIterator> void f(InputIterator first, InputIterator last)
{
  f_impl<
      InputIterator,
      typename std::iterator_traits<InputIterator>::value_type
  >::f(first,last);
};
like image 70
Michael Anderson Avatar answered Sep 19 '22 01:09

Michael Anderson


Using SFINAE, assuming enable_if[_c] and is_same are either from Boost or <type_traits> (and are appropriately qualified with either boost:: or std:: respectively):

template<typename InputIterator>
typename enable_if<
    !is_same<
        typename std::iterator_traits<InputIterator>::value_type,
        SomeSpecificType
    >::value
>::type
f(InputIterator first, InputIterator last)
{
    // Default implementation.
}

template<typename InputIterator>
typename enable_if<
    is_same<
        typename std::iterator_traits<InputIterator>::value_type,
        SomeSpecificType
    >::value
>::type
f(InputIterator first, InputIterator last)
{
    // Special case
}

In the Boost case, use boost::enable_if_c for something similar to the above. You can use boost::enable_if and get rid of the ::value but then must also use e.g. boost::disable_if.

like image 26
Luc Danton Avatar answered Sep 19 '22 01:09

Luc Danton