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!
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));
}