在C++ 11中经常需要定义一个以容器作为参数的函数.
例如,让我们定义一个函数addup(是的只是一个简单的版本std::accumulate):
template <class I>
int addup (I first, I last)
{
int x = 0;
while ( first != last )
x += *first++;
return x;
}
Run Code Online (Sandbox Code Playgroud)
这需要一个迭代器范围,这是灵活的标准库惯用法.
但是假设我有一个功能:
vector<T> f();
Run Code Online (Sandbox Code Playgroud)
我必须这样做:
auto v = f();
int x = addup(v.begin(), v.end());
Run Code Online (Sandbox Code Playgroud)
我宁愿这样做:
int x = addup(f());
Run Code Online (Sandbox Code Playgroud)
就像我可以这样做:
for (auto t : f())
...
Run Code Online (Sandbox Code Playgroud)
本着基于范围的精神,我想要这样的事情:
template<class C>
int addup(C&& container)
{
addup(beginexpr(container), endexpr(container)); // ???
}
Run Code Online (Sandbox Code Playgroud)
在标准中它在6.5.4(释义)中说:
(A)if
container是数组类型,beginexpr并且endexpr …
我正在尝试创建一个接受底层容器的函数,并根据对元素进行一些处理的自定义迭代器返回一个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));
}
Run Code Online (Sandbox Code Playgroud)
代码有效(给定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声明而不将它暴露给整个命名空间?
在他最近的一次演讲中,Herb Sutter建议更喜欢免费的begin(container) end(container)功能模板container.begin().我喜欢它,因为可以为所有不带有begin()/ end()方法的可迭代类型提供这些函数.由于我的大多数域类都具有以域语言进行通信的接口,并且不使用诸如begin/end之类的通用名称,因此我现在可以提供与STL容器兼容的可迭代接口和用于循环的范围,而不会弄乱主类接口.我想知道为我自己的类型提供开始/结束函数的最佳方法是什么.我的第一个想法是以与我一样的方式执行它,swap并在我的类型所在的同一命名空间中编写函数.
namespace My
{
class Book
{
public:
typedef std::vector<Page>::const_iterator PageIterator;
PageIterator FirstPage() const { return begin(pages_); }
PageIterator LastPage() const { return end(pages_); }
private:
std::vector<Page> pages_;
};
Book::PageIterator begin(const Book& b)
{
return b.FirstPage();
}
Book::PageIterator end(const Book& b)
{
return b.LastPage();
}
}
Run Code Online (Sandbox Code Playgroud)
可以在这里依赖ADL,还是应该在std命名空间中?我认为另一种方法是在std命名空间中提供特化(不允许在std中重载,对吧?).特别是关于基于范围的循环查找的最佳方法是什么?