How to implement a container that provides multiple ranges?

I have a container that (among other things) provides a string buffer and an upper case version of this string buffer. (Well, it's not only uppercase, but it is similar in concept). I want the caller to be able to do something similar:

container c("Example"); auto const iter = c.begin() + 2; std::printf("%c\n", iter->get_source()); // Prints a std::printf("%c\n", iter->get_upper()); // Prints A iter->set('x'); std::puts(c.get()); // Prints Exxmple std::puts(c.get_upper()); // Prints EXXMPLE 

The problem is that the type is "proxy" with the member functions get_source , get_upper , etc. there is no obvious place where it can be stored, and the iterator should return a link to something, not a value, ( vector<bool> has a similar task)

As an alternative, I can expose any container or range of the shell or expose completely separate functions of the beginning and end of the iterator. Does anyone have experience doing something similar and know that it works well?

+6
source share
1 answer

My personal approach to such things is to use property maps: I present a system of algorithms that can [optionally] take a property map (or actually sometimes several property maps) for each range. The idea is that *it gives a key (for example, T& , which it currently does), which is then used with a property map, which converts the key into an actually accessible value. A transformation can, for example, be an identity giving the current behavior of the algorithms and a good default value that will be used when there is no property map. The example above looks something like this:

 auto const cursor = c.begin(); std::printf("%c\n", c.map_source()(*cursor)); std::printf("%c\n", c.map_upper()(*cursor)); c.map_source()(*cursor, 'x'); std::copy(c.map_source(), c, std::ostreambuf_iterator<char>(std::cout)); std::copy(c.map_upper(), c, std::ostreambuf_iterator<char>(std::cout)); std::copy([](unsigned char c)->char{ return std::toupper(c); }, c, std::ostreambuf_iterator<char>(std::cout)); 

The code assumes that property maps giving the source and capital characters are obtained using c.map_source() and c.map_upper() , respectively. The last option using std::copy() uses the lambda function as a property map.

Unfortunately, I still have not found time to write a joint proposal on the application of various improvements to the STL algorithms .... and I do not have an implementation that combines all this (I have a somewhat clumsy implementation that is about 10 years old and not use the various C ++ 11 features that make it a lot easier, and this implementation only focuses on property maps and does not use the interface that I currently see).

+1
source

All Articles