如何为您自己的类型提供免费的开始/结束功能

han*_*aad 9 c++ c++11

在他最近的一次演讲中,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中重载,对吧?).特别是关于基于范围的循环查找的最佳方法是什么?

Dav*_*eas 9

我会让ADL做它的工作.虽然您可以在std命名空间中添加特殊化,但是当命名空间中的普通自由函数足够时,我没有理由这样做.

特别是对于循环范围,标准规定:

§6.5.4/ 1(begin-exprend-expr的定义):

  • 否则,开始-expr和end-EXPR是begin(__range)end(__range)表示,其中的开始和结束的查找与参数相关的查找(3.4.2).出于此名称查找的目的,名称空间std是关联的名称空间.


Arm*_*yan 5

完全可以,建议“依靠” ADL。该beginend功能是你的类型的接口的一部分(无论它们是否是独立的功能或没有),他们应该在同一个命名空间的类型。