I am trying to create a pipe implementation that would expose an interface to chain multiple manipulations on some given data while maintaining immutability of the said data. The caveat here is that the manipulations (which are, obviously, just pure functions) should be able to morph the type of the data (e. g. a pipe that is created from an OpenCV mat that should pass through an OCR tool, which would result in a string output). That said, I made this implementation which utilizes std::experimental::any.
class Pipe {
any data;
public:
Pipe (any data) : data(data) {}
any unpack () {
return data;
}
Pipe operator| (function<any(any)> reducer) {
return Pipe(reducer(this->unpack()));
}
Pipe operator|| (any & destination) {
destination = unpack();
return *this;
}
static Pipe from (any data) {
return Pipe(data);
}
};
Pipe::from(some_data) | do_something | do_something_else || unpacked
any_cast
any
any
Template can indeed remove the use of any
, something like:
template <typename T>
class Pipe {
T data;
public:
Pipe (T data) : data(data) {}
const T& unpack () const { return data; }
T& unpack () { return data; }
template <typename F>
auto operator| (F reducer) -> decltype(reducer(std::declval<T>()))
{
return Pipe<decltype(reducer(data))>(reducer(data));
}
Pipe operator|| (T& destination) const
{
destination = unpack();
return *this;
}
};
template <typename T>
Pipe<T> MakePipe(T data) {
return Pipe<T>(data);
}
The usage would be
MakePipe(some_data) | do_something | do_something_else || unpacked;