Previous iteration-memoization with CRTP-interfaces - c++

I have a Curiously Recurring Template Pattern (CRTP) interface-class where I want to memoize evaluations for all methods defined by the derived classes. I also have return values whose types are template-defined. Example:
template <class Derived, class Ret1, class Ret2>
class memoization_class
{
int operator_iter, Eval_1_iter, Eval_2_iter;
double data_operator;
Ret1 data_Eval_1;
Ret2 data_Eval_2;
public:
//Desired memoization:
double operator()(const double &arg, const int& iter)
{
if (iter != operator_iter)
{
data_operator = static_cast<Derived *>(this)->operator(arg);
operator_iter = iter;
return data_operator;
}
else
{
return data_operator;
}
}
//Want to create the same buffer for an arbitrary return type, for an arbitrary amount of methods
Ret1 Eval_1(const double &arg, const int& iter)
{
return static_cast<Derived *>(this)->Eval_1(arg);
}
Ret2 Eval_2(const double &arg, const int& iter)
{
return static_cast<Derived *>(this)->Eval_2(arg);
}
};
Is it possible to generalize this behaviour to something like this:
template <class Derived, class Ret1, class Ret2>
class memoization_class
{
int operator_iter, Eval_1_iter, Eval_2_iter;
double data_operator;
Ret1 data_Eval_1;
Ret2 data_Eval_2;
public:
double operator()(const double &arg, const int& iter)
{
return memoize(&static_cast<Derived *>(this)->operator(), arg, iter);
}
//..
};
Edit: Here is the application for the problem. It uses Eigen, and may return Sparse or Dense matrices/vectors. (The class provides functions for optimizing nonlinear problems)
MatrixBase is in this case a substitute for Vec in order to allow Eigen to pass all kinds of unevaluated expressions.
#ifndef OBJECTIVE_HPP
#define OBJECTIVE_HPP
#include "EigenDataTypes.hpp"
// template <class Base, class Mat>
// using is_Base = std::enable_if_t<std::is_base_of<Base, Mat>::value>;
// template <class Derived, class Vec, class Mat, typename Enable = void>
// struct objective;
template <class Derived, class Vec, class Mat>
struct objective
{
protected:
int Nx_, nnzh_;
public:
objective(const int &Nx, const int &nnzh) : Nx_(Nx), nnzh_(nnzh) {}
template <typename T>
inline scalar operator()(const MatrixBase<T> &x)
{
return static_cast<Derived *>(this)->operator()(x);
}
template <typename T>
inline Vec Eval_grad(const MatrixBase<T> &x)
{
return static_cast<Derived *>(this)->Eval_grad(x);
}
template <typename T>
inline Mat Eval_hessian(const MatrixBase<T> &x)
{
return static_cast<Derived *>(this)->Eval_hessian(x);
}
template <typename T>
inline scalar operator()(const SparseMatrixBase<T> &x)
{
return static_cast<Derived *>(this)->operator()(x);
}
template <typename T>
inline Vec Eval_grad(const SparseMatrixBase<T> &x)
{
return static_cast<Derived *>(this)->Eval_grad(x);
}
template <typename T>
inline Mat Eval_hessian(const SparseMatrixBase<T> &x)
{
return static_cast<Derived *>(this)->Eval_hessian(x);
}
inline int Get_Nx()
{
return Nx_;
}
inline int Get_nnzh()
{
return nnzh_;
}
};
EigenDataTypes.hpp:
#ifndef EIGENDATATYPES_H
#define EIGENDATATYPES_H
#include <Eigen/Dense>
#include <Eigen/Sparse>
using scalar = Eigen::Matrix<double, 1, 1>;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using spVec = Eigen::SparseVector<double>;
using spMat = Eigen::SparseMatrix<double>;
using dVec = Eigen::VectorXd;
using dMat = Eigen::MatrixXd;
using Eigen::MatrixBase;
using Eigen::SparseMatrixBase;
using Triplet = Eigen::Triplet<double>;
#endif
Edit 2: Here is my rather verbose implementation of memoization for the objective-class. (It checks for change in input x instead of iteration-change):
template <class Data>
struct memData
{
dVec x;
Data data;
memData(const int &Nx) : x(Nx)
{
}
};
inline bool
is_memoized(const dVec &x, const dVec &x_mem)
{
return ((x - x_mem).array().abs() <= std::numeric_limits<double>::epsilon()).all();
}
template <class Derived, class Vec, class Mat>
struct objective_memoized : public objective<objective_memoized<Derived, Vec, Mat>, Vec, Mat>
{
protected:
int &Nx_ = objective<objective_memoized<Derived, Vec, Mat>, Vec, Mat>::Nx_;
int &nnzh_ = objective<objective_memoized<Derived, Vec, Mat>, Vec, Mat>::nnzh_;
memData<scalar> mem_operator;
memData<Vec> mem_Eval_grad;
memData<Mat> mem_Eval_hessian;
public:
objective_memoized(const int &Nx, const int &nnzh) : objective<objective_memoized<Derived, Vec, Mat>, Vec, Mat>(Nx, nnzh),
mem_operator(Nx),
mem_Eval_grad(Nx),
mem_Eval_hessian(Nx)
{
}
objective_memoized(const int &Nx, const int &Ns, const int &nnzh) : objective<objective_memoized<Derived, Vec, Mat>, Vec, Mat>(Nx, nnzh),
mem_operator(Nx + Ns),
mem_Eval_grad(Nx + Ns),
mem_Eval_hessian(Nx + Ns)
{
}
template <typename T>
inline scalar operator()(const MatrixBase<T> &x)
{
if (!is_memoized(x, mem_operator.x))
{
mem_operator.data = static_cast<Derived *>(this)->operator()(x);
mem_operator.x = x;
}
return mem_operator.data;
}
template <typename T>
inline Vec Eval_grad(const MatrixBase<T> &x)
{
if (!is_memoized(x, mem_Eval_grad.x))
{
mem_Eval_grad.data = static_cast<Derived *>(this)->Eval_grad(x);
mem_Eval_grad.x = x;
}
return mem_Eval_grad.data;
}
template <typename T>
inline Mat Eval_hessian(const MatrixBase<T> &x)
{
if (!is_memoized(x, mem_Eval_hessian.x))
{
mem_Eval_hessian.data = static_cast<Derived *>(this)->Eval_hessian(x);
mem_Eval_hessian.x = x;
}
return mem_Eval_hessian.data;
}
template <typename T>
inline scalar operator()(const SparseMatrixBase<T> &x)
{
if (!is_memoized(x, mem_operator.x))
{
mem_operator.data = static_cast<Derived *>(this)->operator()(x);
mem_operator.x = x;
}
return mem_operator.data;
}
template <typename T>
inline Vec Eval_grad(const SparseMatrixBase<T> &x)
{
if (!is_memoized(x, mem_Eval_grad.x))
{
mem_Eval_grad.data = static_cast<Derived *>(this)->Eval_grad(x);
mem_Eval_grad.x = x;
}
return mem_Eval_grad.data;
}
template <typename T>
inline Mat Eval_hessian(const SparseMatrixBase<T> &x)
{
if (!is_memoized(x, mem_Eval_hessian.x))
{
mem_Eval_hessian.data = static_cast<Derived *>(this)->Eval_hessian(x);
mem_Eval_hessian.x = x;
}
return mem_Eval_hessian.data;
}
};
TLDR; I want to return stored data if it has been evaluated previously this iteration, or evaluate, store & return if not. Can I use one function to define this for all return types?

Related

template function to handle class and class*

The code below allows me to template a function
taking a parameter which is a vector of one of three different pointer types to Box objects:
const std::vector<std::shared_ptr<Box>>&
const std::vector<std::weak_ptr<Box>>&
const std::vector<Box*>&
Is there a way to extend this to support:
const vector<Box>&
const vector<std::reference_wrapper<Box>>
perhaps something in boost?
#include <vector>
#include <iostream>
class Box{
public:
Box (unsigned int id, unsigned int side): id(id), side(side){}
int volume(){
return side * side * side;
}
unsigned int id;
unsigned int side;
};
template <typename T>
struct is_box_containter {
enum { value = false };
};
template <>
struct is_box_containter <std::vector<std::shared_ptr<Box>>> {
enum { value = true };
};
template <>
struct is_box_containter <std::vector<std::weak_ptr<Box>>> {
enum { value = true };
};
template <>
struct is_box_containter <std::vector<Box*>> {
enum { value = true };
};
template <typename T>
typename std::enable_if<is_box_containter<T>::value>::type
measure(T const& boxes )
{
for (auto& box : boxes) {
std::cout << box->id << " has volume " << box->volume() << std::endl;
}
}
int main (){
std::vector<std::shared_ptr<Box>> some_boxes;
some_boxes.push_back(std::shared_ptr<Box>(new Box(1,4)));
some_boxes.emplace_back(new Box(2, 12));
Box * box_3 = new Box(3, 8);
Box * box_4 = new Box(4, 9);
std::vector<Box*> more_boxes;
more_boxes.emplace_back(box_3);
more_boxes.emplace_back(box_4);
measure(some_boxes);
measure(more_boxes);
return 0;
}
Why I am asking this question:
I have an application with two functions which implement near identical logic. One takes a list of SomeClass, the other takes a vector of pointers to SomeClass.
I am currently planning on refactoring the code to replace the list of SomeClass with a list of shared pointers to SomeClass. But the only reason I am doing this is to move the logic to a common implementation. I don't want to do that if there is a perfectly reasonable way to avoid it.
If I understood your question correctly, you could use a dereferencing mechanism like below:
template<typename T>
T& dereference(T &v) {
return v;
}
template<typename T>
const T& dereference(const T& v) {
return v;
}
template<typename T>
typename std::enable_if<!std::is_function<T>::value, T&>::type dereference(T* v) {
return dereference(*v);
}
template<typename T>
const T& dereference(const std::shared_ptr<T>& v) {
return dereference(*v);
}
template<typename T>
const T& dereference(const std::weak_ptr<T>& v) {
return dereference(*v);
}
template<typename T>
const T& dereference(const std::reference_wrapper<T>& v) {
return v;
}
and then call your data like:
template <typename T>
typename std::enable_if<is_box_containter<T>::value>::type
measure(T const& boxes )
{
for (auto& box : boxes) {
std::cout << dereference(box).id
<< " has volume " << dereference(box).volume() << std::endl;
}
}
LIVE DEMO
P.S You'll also have to define:
template <>
struct is_box_containter <std::vector<Box>> {
enum { value = true };
};
template <>
struct is_box_containter <std::vector<std::reference_wrapper<Box>>> {
enum { value = true };
};

Container for different functions?

I'm trying to implement a container class for different functions where I can hold function pointers and use it to call those functions later. I'll try to discribe my problem more accurate.
As example, I have 2 different test functions:
int func1(int a, int b) {
printf("func1 works! %i %i\n", a, b);
return 0;
}
void func2(double a, double b) {
printf("func2 works! %.2lf %.2lf\n", a, b);
}
and I also have array of variants, which holds function arguments:
std::vector<boost::variant<int, double>> args = {2.2, 3.3};
I've decided to use my own functor class derived from some base class ( I thought about using virtual methods):
class BaseFunc {
public:
BaseFunc() {}
~BaseFunc() {}
};
template <typename T>
class Func;
template <typename R, typename... Tn>
class Func<R(Tn...)> : public BaseFunc {
typedef R(*fptr_t)(Tn...);
fptr_t fptr;
public:
Func() : fptr(nullptr) {}
Func(fptr_t f) : fptr(f) {}
R operator()(Tn... args) {
return fptr(args...);
}
Func& operator=(fptr_t f) {
fptr = f;
return *this;
}
};
Also I've decided to store some information about function and its arguments:
struct TypeInfo {
int type_id; // for this example: 0 - int, 1 - double
template <class T>
void ObtainType() {
if (std::is_same<void, T>::value)
type_id = 0;
else if (std::is_same<int, T>::value)
type_id = 1;
else if (std::is_same<double, T>::value)
type_id = 2;
else
type_id = -1;
}
};
struct FunctionInfo {
public:
FunctionInfo() {}
FunctionInfo(BaseFunc *func, const TypeInfo& ret, std::vector<TypeInfo>& args) :
func_ptr(func), return_info(ret)
{
args_info.swap(args);
}
~FunctionInfo() {
delete func_ptr;
}
BaseFunc * func_ptr;
TypeInfo return_info;
std::vector<TypeInfo> args_info;
};
So now I can define a container class:
class Container {
private:
template <size_t n, typename... T>
void ObtainTypeImpl(size_t i, TypeInfo& t)
{
if (i == n)
t.ObtainType<std::tuple_element<n, std::tuple<T...>>::type>();
else if (n == sizeof...(T)-1)
throw std::out_of_range("Tuple element out of range.");
else
ObtainTypeImpl<(n < sizeof...(T)-1 ? n + 1 : 0), T...>(i, t);
}
template <typename... T>
void ObtainType(size_t i, TypeInfo& t)
{
return ObtainTypeImpl<0, T...>(i, t);
}
public:
template <class R, class ...Args>
void AddFunc(const std::string& str, R(*func)(Args...)) {
BaseFunc * func_ptr = new Func<R(Args...)>(func);
size_t arity = sizeof...(Args);
TypeInfo ret;
ret.ObtainType<R>();
std::vector<TypeInfo> args;
args.resize(arity);
for (size_t i = 0; i < arity; ++i)
{
ObtainType<Args...>(i, args[i]);
}
cont_[str] = FunctionInfo(func_ptr, ret, args);
}
void CallFunc(const std::string& func_name,
std::vector<boost::variant<int, double>>& args_vec) {
auto it = cont_.find(func_name);
if (it != cont_.end())
{
// ???????
// And here I stucked
}
}
private:
std::map<std::string, FunctionInfo> cont_;
};
And then I stucked.
Don't know how to get function type information from my struct :).
Don't know how to convert vector of variants to arguments list.
Maybe my path was wrong? Can you suggest any solution of this problem except script engine like Lua?
You may do something like:
class BaseFunc {
public:
virtual ~BaseFunc() = default;
virtual void Call(std::vector<boost::variant<int, double>>& args_vec) const = 0;
};
template <typename F> class Function;
template <typename R, typename... Args> class Function<R(Args...)> : public BaseFunc
{
public:
Function(R (*f)(Args...)) : f(f) {}
void Call(std::vector<boost::variant<int, double>>& args_vec) const override
{
Call(args_vec, std::index_sequence_for<Args...>());
}
private:
template <std::size_t ... Is>
void Call(
std::vector<boost::variant<int, double>>& args_vec,
std::index_sequence<Is...>) const
{
// Add additional check here if you want.
f(boost::get<Args>(args_vec.at(Is))...);
}
private:
R (*f)(Args...);
};
Live example

accessing members of a templated class with variable numbers of templated arguments

I have a templated class with variable numbers of templated arguments. As in these cases (I cannot afford C++11) a good practice is to create a default class that we call none and put it as default like below.
struct none {};
template<class T1=none, T2=none, T3=none>
class A{
template<class T>
double extract() { return none();}
template<>
double extract<T1>() { return m1_();}
template<>
double extract<T2>() { return m2_();}
template<>
double extract<T3> () { return m3_();}
T1 m1_;
T2 m2_;
T3 m3_;
};
At this stage I don't know how to implement a generic/templated accessor function that can access each of the templated argument.
All of the templated arguments are different so I specialized A::extract() for each of the templated arguments.
Is there any better way to do this? Any sort of tagging I can have a look at?
struct none {};
template <class T, class N>
class Holder : public N
{
protected:
T m;
typedef Holder<T, N> First;
double extractP(T*) { return m(); }
template <class X> double extractP(X*) {
return this->N::extractP(static_cast<X*>(0));
}
};
template <class T>
class Holder<T, none>
{
protected:
T m;
typedef Holder<T, none> First;
double extractP(T*) { return m(); }
template <class X> none extractP(X*) {
return none();
}
};
template <class T1 = none, class T2 = none, class T3 = none>
class A : Holder<T1, Holder<T2, Holder<T3, none> > >
{
public:
template <class T> double extract() {
return this->extractP(static_cast<T*>(0));
}
};
A similarly-named solution to n.m but more on the Boost's Variant class design.
The suggestion is to use a Variant container (a generic container for your objects) and use accessors directly on them.
#include <iostream>
#include <stdexcept>
using namespace std;
class BaseHolder
{
public:
virtual ~BaseHolder(){}
virtual BaseHolder* clone() const = 0;
};
template<typename T>
class HoldData : public BaseHolder
{
public:
HoldData(const T& t_) : t(t_){}
virtual BaseHolder* clone() const {
return new HoldData<T>(t);
}
T getData() {
return t;
}
private:
T t;
};
class Variant
{
public:
Variant() : data(0) {}
template<typename T>
Variant(const T& t) : data(new HoldData<T>(t)){}
Variant(const Variant& other) : data(other.data ? other.data->clone() : 0) {}
~Variant(){delete data;}
template<typename T>
T getData() {
return ((HoldData<T>*)data)->getData();
}
private:
BaseHolder* data;
private:
Variant& operator=(const Variant& other) { return *this;} // Not allowed
};
struct none {};
class Container{
public:
Container() : m1_(0), m2_(0), m3_(0){}
~Container() {
if(m1_)
delete m1_;
if(m2_)
delete m1_;
if(m3_)
delete m1_;
}
none extract() { return none();}
template<typename T>
void insertM1(T obj) {
m1_ = new Variant(obj);
}
template<typename T>
T extractM1() {
if(m1_ != 0)
return m1_->getData<T>();
else
throw std::runtime_error("Element not set");
}
// TODO: implement m2 and m3
Variant *m1_;
Variant *m2_;
Variant *m3_;
};
int main() {
Container obj;
char M1 = 'Z';
obj.insertM1(M1);
char extractedM1 = obj.extractM1<char>();
cout << extractedM1;
return 0;
}
http://ideone.com/BaCWSV
Your class seems to mimic std::tuple, which, unfortunately for you, was added in C++11. The good news is that you can use boost::tuple instead.
As an example of usage:
boost::tuple<std::string, double> t = boost::make_tuple("John Doe", 4.815162342);
std::cout << boost::get<0>(t) << '\n';
std::cout << boost::get<1>(t) << '\n';
Live demo
Without access to C++11, it's a bit uglier, but you can leverage Boost.Tuple:
#include <iostream>
#include <boost/tuple/tuple.hpp>
template <size_t I, typename T, typename U>
struct AccessImpl;
template <size_t I, typename T, typename U>
struct AccessImpl {
template <typename Tuple>
static T& impl(Tuple& tuple) {
typedef typename ::boost::tuples::element<I+1, Tuple>::type Next;
return AccessImpl<I+1, T, Next>::impl(tuple);
}
};
template <size_t I, typename T>
struct AccessImpl<I, T, T> {
template <typename Tuple>
static T& impl(Tuple& tuple) { return boost::get<I>(tuple); }
};
template <typename T, typename Tuple>
T& access(Tuple& tuple) {
typedef typename ::boost::tuples::element<0, Tuple>::type Head;
return AccessImpl<0, T, Head>::impl(tuple);
}
int main() {
boost::tuples::tuple<char, int, std::string> example('a', 1, "Hello, World!");
std::cout << access<std::string>(example) << "\n";
return 0;
}
This, as expected, prints "Hello, World!".

Select C++ template specialization based on member type availability

I am writing a sort of serialization class. It must provide functions for containers. Current implementation is:
template <typename InsertIter>
bool readContainer(InsertIter result)
{
typedef typename InsertIter::container_type::value_type tVal;
UInt32 size = 0;
if (!read(size))
return false;
for (UInt32 i = 0; i < size; ++i)
{
tVal val;
if (!read(val))
return false;
*result++ = val;
}
return true;
}
template <typename InsertIter>
bool readMap(InsertIter result)
{
typedef typename InsertIter::container_type::key_type tKey;
typedef typename InsertIter::container_type::mapped_type tVal;
UInt32 size = 0;
if (!read(size))
return false;
for (UInt32 i = 0; i < size; ++i)
{
std::pair<tKey, tVal> pair;
if (!read(pair))
return false;
*result++ = pair;
}
return true;
}
As you can see, I must to create different implementations for map-like types (std::map) and other containers, because std::map::value_type is std::pair(const K, V) and not std::pair(K, V).
So, I want to create method read(InsertIter) which will automatically select appropriate readContainer(InsertIter) or readMap(InsertIter). Is this possible?
I have an example that does something very similar, and it should be very simple for you to convert to something that you need :
#include <iostream>
template< typename T >
struct A;
template<>
struct A< int >
{
void foo() const
{
std::cout<<"A(int)::foo()"<<std::endl;
}
};
template<>
struct A< float >
{
void foo() const
{
std::cout<<"A(float)::foo()"<<std::endl;
}
};
template< typename T >
void call( const A<T> &a)
{
a.foo();
}
struct B
{
template<typename T>
void bar(const A<T> &a)
{
call(a);
}
};
int main()
{
A<int> a1;
A<float> a2;
B b;
b.bar(a1);
b.bar(a2);
}
You need to give proper names, and replace int and float in the above example with appropriate container types, and implement needed functionality.
I have successfully solved my problem.
Thanks to Johan Lundberg and especially to n.m. - I was not familiar with SFINAE idiom and your links and samples helped me a lot.
I was not able to use C++11 features (project specifics), but they are not needed.
Current code looks like this:
struct SFINAE
{
typedef char __one;
typedef struct { char __arr[2]; } __two;
};
template <typename T>
class has_mapped_type : public SFINAE
{
template <typename C> static __one test(typename C::mapped_type *);
template <typename C> static __two test(...);
public:
enum { value = (sizeof(test<T>(0)) == sizeof(__one)) };
};
class Serializer
{
template <typename InsertIter>
bool read(InsertIter result) const
{
return readContainerSelector< InsertIter,
has_mapped_type<typename InsertIter::container_type>::value
> ::read(result, *this);
}
template <typename InsertIter, bool isMapType>
struct readContainerSelector;
template <typename InsertIter>
struct readContainerSelector<InsertIter, true>
{
static bool read(InsertIter result, Serializer const& ser)
{
return ser.readMap(result);
}
};
template <typename InsertIter>
struct readContainerSelector<InsertIter, false>
{
static bool read(InsertIter result, Serializer const& ser)
{
return ser.readContainer(result);
}
};
// methods from my topic post
template <typename InsertIter> bool readContainer(InsertIter result);
template <typename InsertIter> bool readMap(InsertIter result)
};

C++ Iterator Pipelining Designs

Suppose we want to apply a series of transformations, int f1(int), int f2(int), int f3(int), to a list of objects. A naive way would be
SourceContainer source;
TempContainer1 temp1;
transform(source.begin(), source.end(), back_inserter(temp1), f1);
TempContainer2 temp2;
transform(temp1.begin(), temp1.end(), back_inserter(temp2), f2);
TargetContainer target;
transform(temp2.begin(), temp2.end(), back_inserter(target), f3);
This first solution is not optimal because of the extra space requirement with temp1 and temp2. So, let's get smarter with this:
int f123(int n) { return f3(f2(f1(n))); }
...
SourceContainer source;
TargetContainer target;
transform(source.begin(), source.end(), back_inserter(target), f123);
This second solution is much better because not only the code is simpler but more importantly there is less space requirement without the intermediate calculations.
However, the composition f123 must be determined at compile time and thus is fixed at run time.
How would I try to do this efficiently if the composition is to be determined at run time? For example, if this code was in a RPC service and the actual composition--which can be any permutation of any subset of f1, f2, and f3--is based on arguments from the RPC call.
EDIT: Working version at http://ideone.com/5GxnW . The version below has the ideas but does not compile. It supports run time type checking, and run time function composition.
The idea is to define a generic (unary) function class, and a way to compose them with run time type checks. This is done with a combination of boost::any, boost::function and the type erasure idiom.
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
template <typename T>
struct identity
{
T operator()(const T& x) { return x; }
};
struct any_function
{
template <typename Res, typename Arg>
any_function(boost::function<Res, Arg> f)
{
impl = make_impl(f);
}
boost::any operator()(const boost::any& x)
{
return impl->invoke(x);
}
static any_function compose(const any_function& f,
const any_function& g)
{
any_function ans;
ans.impl = compose_impl(f.impl, g.impl);
return ans;
}
template <typename T>
static any_function id()
{
using boost::function
return any_function(function<T(T)>(identity<T>()));
}
template <typename Res, typename Arg>
boost::function<Res(Arg)> to_function()
{
using boost::function;
return function<Res(Arg)>(to_function_helper(impl));
}
private:
any_function() {}
struct impl_type
{
virtual ~impl_type() {}
virtual boost::any invoke(const boost::any&) = 0;
};
boost::shared_ptr<impl_type> impl;
template <typename Res, typename Arg>
static impl_type* make_impl(boost::function<Res(Arg)> f)
{
using boost::function;
using boost::any;
using boost::any_cast;
class impl : public impl_type
{
function<Res(Arg)> f;
any invoke(const any& x)
{
const Arg& a = any_cast<Arg>(x);
return any(f(a));
}
public:
impl(function<Res(Arg)> f) : f(f) {}
};
return new impl(f);
}
impl_type* compose_impl(boost::shared_ptr<impl_type> f,
boost::shared_ptr<impl_type> g)
{
using boost::any;
using boost::shared_ptr;
class impl : public impl_type
{
shared_ptr<impl> f, g;
any invoke(const any& x)
{
return g->invoke(f->invoke(x));
}
public:
impl(const shared_ptr<impl>& f,
const shared_ptr<impl>& g)
: f(f), g(g)
{}
};
return new impl(f, g);
}
struct to_function_helper
{
template <typename Res, typename Arg>
Res operator()(const Arg& x)
{
using boost::any;
using boost::any_cast;
return any_cast<Res>(p->invoke(any(x)));
}
to_function_helper(const boost::shared_ptr<impl>& p) : p(p) {}
private:
boost::shared_ptr<impl> p;
};
};
Now, let's use standard algorithms and do this (this even works on empty sequences):
// First function passed is evaluated first. Feel free to change.
template <typename Arg, typename Res, typename I>
boost::function<Res(Arg)> pipeline(I begin, I end)
{
return std::accumulate(begin, end,
any_function::id<Arg>,
std::ptr_fun(any_function::compose)
).to_function<Res, Arg>();
}
and use the following to apply it
std::vector<any_function> f;
std::vector<double> v;
std::vector<int> result;
std::transform(v.begin(), v.end(),
result.begin(),
pipeline<double, int>(f.begin(), f.end())
);
You can even use boost::transform_iterator
typedef boost::transform_iterator<
boost::function<double, int>,
std::vector<double>::const_iterator
> iterator;
boost::function<double, int> f = pipeline<double, int>(f.begin(), f.end());
std::copy(iterator(v.begin(), f), iterator(v.end(), f), result.begin());
template<class T>
class compose {
typedef T (*f)(T);
f first_func;
f second_func;
public:
compose(f one,f two) :
first_func(one),
second_func(two)
{}
T operator()(T const &input) {
T temp = first_func(input);
return second_func(temp);
}
};
#ifdef TEST
int f(int x) { return 8 + x; }
int g(int x) { return 2 * x; }
int h(int x) { return x * x; }
#include <iostream>
int main(int argc, char **argv) {
compose<int> x(f, g);
compose<int> y(g, f);
std::cout << x(6) << std::endl;
std::cout << y(6) << std::endl;
typedef int (*func)(int);
func funcs[] = {f, g, h};
compose<int> z(funcs[atoi(argv[1])], funcs[atoi(argv[2])]);
std::cout << z(6);
return 0;
}
#endif
With C++0x, we should be able to use auto to eliminate having to specify the argument/return type. For the moment I've assumed they're the same, though in theory, you might like the ability to include conversions in the mix.
you should use a functor instead of function and pass needed transform functions into functor's constructor
something like
typedef int (*FunctionType)(int);
class Functor
{
FunctionType m_f1;
FunctionType m_f2;
FunctionType m_f3;
public:
Functor(FunctionType f1, FunctionType f2, FunctionType f3):
m_f1(f1), m_f2(f2), m_f3(f3)
{}
int operator()(int n)
{
return (*m_f1)((*m_f2)((*m_f3)(n)));
}
};
// ...
transform(source.begin(), source.end(), back_inserter(temp1), Functor(f1,f2,f3));
if you need variable number of functions then change Functor constructor signature to use vector of functions and fill that vector before calling transform.
Just define an iterator that does what you want:
template<typename T>
struct source
{
virtual source<T>& operator++(void) = 0;
virtual T operator*(void) = 0;
virtual bool atend() = 0;
};
struct source_exhausted
{
};
template<typename T>
bool operator==(const source<T>& comparand, const source_exhausted&)
{ return comparand.atend(); }
template<typename T>
bool operator!=(const source<T>& comparand, const source_exhausted&)
{ return !comparand.atend(); }
template<typename T>
bool operator==(const source_exhausted&, const source<T>& comparand)
{ return comparand.atend(); }
template<typename T>
bool operator!=(const source_exhausted&, const source<T>& comparand)
{ return !comparand.atend(); }
template<typename T, typename iterT, typename endT>
struct source_iterator : source<T>
{
iterT m_iter;
endT m_end;
source_iterator(iterT iter, endT end) : m_iter(iter), m_end(end) {}
virtual source<T>& operator++(void) { ++m_iter; return *this; }
virtual T operator*(void) { return *m_iter; }
virtual bool atend() { return m_iter == m_end; }
};
template<typename T, typename iterT, typename endT>
auto make_source_iterator(iterT iter, endT end) -> source_iterator<decltype(*iter), iterT, endT>
{
return source_iterator<decltype(*iter), iterT, endT>(iter, end);
}
template<typename TContainer>
auto make_source_iterator(TContainer& c) -> source_iterator<typename TContainer::value_type, decltype(c.begin()), decltype(c.end())>
{
return source_iterator<typename TContainer::value_type, decltype(c.begin()), decltype(c.end())>(c.begin(), c.end());
}
template<typename TIn, typename TOut, typename TXform>
struct source_transformer : source<TOut>
{
source<TIn>& m_src;
TXform const m_f;
source_transformer( source<TIn>& src, TXform f ) : m_f(f), m_src(src) {}
virtual source<TOut>& operator++(void) { ++m_src; return *this; }
virtual TOut operator*(void) { return m_f(*m_src); }
virtual bool atend() { return m_src.atend(); }
};
template<typename TIn, typename TOut, typename TXform>
auto make_source_transformer(source<TIn>& src, TXform f) -> source_transformer<TIn, decltype(f(*(TIn*)0)), TXform>
{
return source_transformer<TIn, decltype(f(*(TIn*)0)), TXform>(src, f);
}
typedef int (*f_t)(int);
int f1(int a) { return a + 1; }
int f2(int a) { return a * 2; }
int f3(int a) { return a * a; }
int main()
{
std::vector<f_t> ff = {f1, f2, f3};
std::vector<int> source = {1, 2, 3, 4}, target;
std::transform(source.begin(), source.end(), std::back_inserter(target)
, [&](int a) { for (f_t &f : ff) a = f(a); return a; });
// print target
std::copy(target.begin(), target.end(), std::ostream_iterator<int,char>(std::cout,"\n"));
system("pause");
return 0;
}