我正在尝试创建一个接受底层容器的函数,并根据对元素进行一些处理的自定义迭代器返回一个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可以工作(如下所示: 依赖于ADL for std :: begin()和std :: end()?)。
我想在C ++ 14中,我可以在这里使用自动返回类型。有C ++ 11解决方案吗?有没有办法让返回类型看到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中,您不需要尾随返回类型,但也需要执行相同的操作 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));
}