In one of his latest talks, Herb Sutter recommended to prefer the free begin(container)
end(container)
functions templates over container.begin()
. I like it, because these function can be provided for all iterable types that don't come with begin()/end() methods. Since most of my domain classes have interfaces that talk in the domain language and don't use general names like begin/end, I can now provide an iterable interface compatible to STL containers and range base for loops without messing up the main class interface.
I am wondering what is the best way to provide begin/end functions for my own types. My first thought was to do it the same way I do with swap
and write the function in the same namespace where my type lives.
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();
}
}
Is it ok to rely in ADL here, or should they be in std namespace? I think another way is to provide a specialization in std namespace (overloading in std is not allowed, right?). What is the best way espacially regarding lookup for range based for loops?
I would let ADL do its work. While you are allowed to add specializations in the std
namespace, there is no strong reason I can think of for doing so when a plain free function in your namespace suffices.
In particular for the range for loops, the standard states:
§6.5.4/1 (definition of begin-expr and end-expr):
- otherwise, begin-expr and end-expr are
begin(__range)
andend(__range)
, respectively, where begin and end are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespace std is an associated namespace.
It's perfectly OK and recommended to "rely" on ADL. The begin
and end
functions are part of your type's interface (regardless of whether they are freestanding functions or not) and they should be in the same namespace as your type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With