Применить с помощью оператора к типу возвращаемого значения функции без применения ко всему пространству имен
Я пытаюсь создать функцию, которая берет базовый контейнер, и возвращает boost:: iterator_range на основе пользовательского итератора, который выполняет некоторую обработку элементов.
например.
// 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));
}
Работает код (с учетом соответствующих определений для CustomIterator и make_custom_range_from_iterators).
Меня беспокоит объявление using std::begin
, которое, я думаю, приведет к тому, что std:: begin будет импортирован во все пространство имен, где объявлена моя функция. Я предпочитаю не использовать std:: begin явно в decltype, чтобы ADL мог работать (как в этом вопросе: Опираясь на ADL для std:: begin() и std:: end ( )?).
Я думаю, что в С++ 14 я мог бы использовать здесь тип автоматического возврата. Есть ли решение С++ 11? Есть ли способ, чтобы возвращаемый тип отображался в объявлении using, не подвергая его всему пространству имен?
Ответы
Ответ 1
Поместите объявление использования в отдельное пространство имен:
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
Ответ 2
Бросьте все в другое пространство имен и разместите там using
. Затем добавьте новых помощников в свое верхнее пространство имен:
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>()));
В С++ 14 вам не понадобятся типы возвращаемых возвратов, но также необходимо будет сделать то же самое для cbegin
и cend
. При этом вам не нужно помнить о том, чтобы снова иметь using
и просто использовать методы adl_*
:
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));
}