Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 906
happydave Avatar asked Sep 08 '15 18:09

happydave


People also ask

What is using () in C#?

The using statement causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and can't be modified or reassigned. A variable declared with a using declaration is read-only.

Is it necessary to define all types in namespace in C#?

Console. WriteLine()” “System” is a namespace in which we have a class named “Console” whose method is “WriteLine()“. It is not necessary to keep each class in C# within Namespace but we do it to organize our code well.

How can a function return a value in C#?

Return valuesIf the return type (the type listed before the method name) is not void , the method can return the value by using the return statement. A statement with the return keyword followed by a value that matches the return type will return that value to the method caller.

What is namespace used for in C#?

The namespace keyword is used to declare a scope that contains a set of related objects. You can use a namespace to organize code elements and to create globally unique types.


2 Answers

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

like image 143
Piotr Skotnicki Avatar answered Oct 22 '22 06:10

Piotr Skotnicki


Throw everything into another namespace and put your usings in there. Then bring your new helpers into your top namespace:

namespace details {
    using std::begin;
    using std::end;

    template <typename C>
    auto adl_begin(C&& c) -> decltype(begin(std::forward<C>(c))) {
        return begin(std::forward<C>(c));
    }

    template <typename C>
    auto adl_end(C&& c) -> decltype(end(std::forward<C>(c))) {
        return end(std::forward<C>(c));
    }
}

using details::adl_begin;
using details::adl_end;

template <typename C>
using adl_begin_t = decltype(adl_begin(std::declval<C>()));

template <typename C>
using adl_end_t = decltype(adl_end(std::declval<C>()));

In C++14, you won't need the trailing return types, but will also need to do the same for cbegin and cend. With that, you don't have to remember to have the usings ever again and just use the adl_* methods everywhere:

template <class Container>
CustomRange<adl_begin_t<Container&>> make_custom_range(Container& c) {
    return make_custom_range_from_iterators(adl_begin(c), adl_end(c));
}
like image 40
Barry Avatar answered Oct 22 '22 05:10

Barry