c++stliterator-traitssgi

How to understand the usage of this template in STL source code?


I am currently viewing the source code of SGI STL, specifically the algorithm of distance.

As I can see, to maximize the efficiency, SGI used a lot inline template to minimize the running time. But I do NOT really understand one thing.

For the algorithm distance, SGI define one template:

template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&){
  typedef typename iterator_traits<Iterator>::iterator_category category;
  return category();
}

And then, it defined the public interface of the algorithm distance like

template <class Iterator>
inline iterator_traits<Iterator>::iterator_category
distance(InputIterator first, InputIterator last)
{
  typedef typename iterator_traits<InputIterator>::iterator_category category;
  return __distance(first, last, category());
}

Before you get all judgements on my knowledge, I want to say that I think understand the design pattern of STL and I understand the meaning of each line, I mean syntax.

But according to what I know, I just don't know why SGI did not implement algorithm distance like

template <class Iterator>
inline iterator_traits<Iterator>::iterator_category
distance(InputIterator first, InputIterator last)
{
  return __distance(first, last, iterator_category<InputIterator>(first));
}

Based on my knowledge, function call will consume certain amount of time, but here, iterator_category is inline function, which has the same effect like macro in most mainstream compilers.

The only shortage of using iterator_category() would potentially be the temporary object generated by compiler because of pass-by-const-reference.

Am I right? Or is there any genius design patter that I did not recognized yet, free to let me know!


Solution

  • Using iterator_category<InputIterator>(first) in implementation might be hijacked with ADL for custom iterator.

    namespace HiJack
    {
    class MyIter{/*..*/};
    
    template <class T> // would be not templated with call like iterator_category(first)
    auto iterator_category(const MyIer&){ /*..*/ }
    }
    

    You might think that is the same for __distance in __distance(first, last, category());, but names with __ are reserved and cannot be used by regular user.

    But fully qualified the call would solve that (assuming namespace sgi):

    template <class Iterator>
    inline iterator_traits<Iterator>::iterator_category
    distance(InputIterator first, InputIterator last)
    {
      return __distance(first, last, ::sgi::iterator_category<InputIterator>(first));
    }