Search code examples
c++c++11argument-dependent-lookup

Apply using statement to the return type of a function without applying to the entire namespace


I'm trying to create a function that takes an underlying container, and returns a boost::iterator_range based on a custom iterator that does some processing on the elements.

E.g.

// The range class, templated on the underlying iterator type
template<class Iter> using CustomRange = boost::iterator_range<CustomIterator<Iter>>;

using std::begin;
template <class Container>
auto make_custom_range(Container& c) -> CustomRange<decltype(begin(c))> {
    using std::end;
    return make_custom_range_from_iterators(begin(c),end(c));
}

The code works (given suitable definitions for CustomIterator and make_custom_range_from_iterators).

My concern is the using std::begin declaration, which I think will cause std::begin to be imported into the entire namespace where my function is declared. I prefer not to use std::begin explicitly in the decltype so that ADL can work (as in this question: Relying on ADL for std::begin() and std::end()?).

I think in C++14, I could just use an auto return type here. Is there a C++11 solution? Is there a way to let the return type see the using declaration without exposing it to the entire namespace?


Solution

  • Put the using declaration in a separate namespace:

    namespace adl_helper
    {
        using std::begin;
    
        template <typename T>
        auto adl_begin(T&& t) -> decltype(begin(std::forward<T>(t)));  
    }
    
    template <class Container>
    auto make_custom_range(Container& c)
        -> CustomRange<decltype(adl_helper::adl_begin(c))>
    //                          ~~~~~~~~~~~~~~~~~~~~^
    {
        using std::begin;
        using std::end;
        return make_custom_range_from_iterators(begin(c),end(c));
    }
    

    DEMO