将 using 语句应用于函数的 return 类型,而不应用于整个命名空间

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

我正在尝试创建一个接受底层容器的函数,并且 return 是一个 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 被导入到声明我的函数的整个名称空间中。我不想在 decltype 中显式使用 std::begin 以便 ADL 可以工作(如在这个问题中:Relying on ADL for std::begin() and std::end()?)。

我认为在 C++14 中,我可以在这里使用自动 return 类型。有 C++11 解决方案吗?有没有办法让 return 类型看到 using 声明而不将其暴露给整个命名空间?

将 using 声明放在单独的命名空间中:

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

将所有内容都放入另一个命名空间并将您的 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>()));

在 C++14 中,您不需要尾随的 return 类型,但也需要对 cbegincend 执行相同的操作。这样,您就不必再记住 usings,只需在任何地方使用 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));
}