Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I specialize std::begin and std::end for the return value of equal_range()?

The <algorithm> header provides std::equal_range(), as well as some containers having it as a member function. What bothers me with this function is that it returns a pair of iterators, making it tedious to iterate from the begin iterator to the end iterator. I'd like to be able to use std::begin() and std::end() so that I can use the C++11 range-based for-loop.

Now, I've heard contradictory information in regards to specializing std::begin() and std::end() - I've been told that adding anything to the std namespace results in undefined behavior, whereas I have also been told that you can provide your own specializations of std::begin() and std::end().

This is what I am doing right now:

namespace std
{
    template<typename Iter, typename = typename iterator_traits<Iter>::iterator_category>
    Iter begin(pair<Iter, Iter> const &p)
    {
        return p.first;
    }
    template<typename Iter, typename = typename iterator_traits<Iter>::iterator_category>
    Iter end(pair<Iter, Iter> const &p)
    {
        return p.second;
    }
}

And this does work: http://ideone.com/wHVfkh

But I am wondering, what are the downsides to doing this? Is there a better way to do this?

like image 428
LB-- Avatar asked Oct 11 '13 19:10

LB--


1 Answers

17.6.4.2.1/1 The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

So yes, I believe that, technically, your code exhibits undefined behavior. Perhaps you can write a simple class that takes a pair of iterators in its constructor and implements begin() and end() methods. Then you can write something like

for (const auto& elem: as_range(equal_range(...))) {}
like image 56
Igor Tandetnik Avatar answered Oct 19 '22 19:10

Igor Tandetnik