mardi 31 mars 2015

Can I create an empty range (iterator pair) without an underlying container object?

I have a class akin to the following:



struct Config
{
using BindingContainer = std::map<ID, std::vector<Binding>>;
using BindingIterator = BindingContainer::mapped_type::const_iterator;

boost::iterator_range<BindingIterator> bindings(ID id) const;
private:
BindingContainer m_bindings;
};


Since the ID passed to bindings() might not exist, I need to be able to represent a 'no bindings' value in the return type domain.


I was hoping to be able to do so with the interface as above and default-construct the iterators, but although a ForwardIterator is DefaultConstructible [N3337 24.2.5/1] the result of comparing a singular iterator is undefined [24.2.1/5], so without a container it seems this is not possible.


I could change the interface to e.g wrap the iterator_range in a boost::optional, or return a vector value instead; the former is a little more clunky for the caller though, and the latter has undesirable copy overheads.


Another option is to keep a statically-allocated empty vector and return its iterators. The overhead wouldn't be problematic in this instance, but I'd like to avoid it if I can.


Adapting the map iterator to yield comparable default-constructed iterators is a possibility, though seems over-complex...


Are there any other options here that would support returning an empty range when there is no underlying container?


(Incidentally I'm sure a while back I read a working paper or article about producing empty ranges for standard container type when there is no container object, but can't find anything now.)


(Note I am limited to C++11 features, though I'd be interested if there is any different approach requiring later features.)


Aucun commentaire:

Enregistrer un commentaire