I'm trying to pass an object to boost::adaptors::transformed. However, this only seems to work if that object's class defines const versions of begin and end. This is not the case for me however, because iterating over an object of this class modifies internal state of the object itself. Here is a minimal example using a dummy class Vector that only exposes non the const versions begin and end or its _v member, what can I change to make this work?
#include <initializer_list>
#include <vector>
#include <boost/range/adaptors.hpp>
template<typename T>
class Vector
{
public:
using value_type = typename std::vector<T>::value_type;
using reference = typename std::vector<T>::reference;
using iterator = typename std::vector<T>::iterator;
Vector(std::initializer_list<T> init)
: _v(init)
{}
iterator begin() { return _v.begin(); }
iterator end() { return _v.end(); }
private:
std::vector<T> _v;
};
int main()
{
Vector<int> v{1, 2, 3, 4};
auto t = [](int i){ return 2 * i; };
auto range(v | boost::adaptors::transformed(t)); // does not compile
}
I'd say in general it's a code smell that iteration modifies a collection.
Of course, something can be logically const, which is what we have the
mutablekeyword for. There's roughly two approaches I can seeMake The Container Storage Mutable
Live On Compiler Explorer
Prints
Purer Approach: Mutable Element Data
For fun, let's make an Element that tracks the number of times its value was observed:
Live On Compiler Explorer
Prints