Overloaded Template Classes - c++

I'm working on a property-like system in c++, one component of which in an accessor template class, which creates static functions I can then pass pointers of, into my property class for get an set operations.
Here's what the accessor looks like:
template <typename T, typename V, V (T::*getf)(), void (T::*setf)(V)>
struct Accessor
{
static V Get(T* obj)
{
return (obj->*getf)();
}
static void Set(T* obj, V aValue)
{
return (obj->*setf)(aValue);
}
};
And a test class that I'll be using the accessor on. Note how SetFoo takes an int, where SetBar takes a const int&.
class TargetClass
{
int foo;
int bar;
public:
TargetClass(int f, int b)
: foo(f)
, bar(b)
{
}
int GetFoo()
{
return foo;
}
void SetFoo(int f)
{
foo = f;
}
int GetBar()
{
return bar;
}
void SetBar(const int& b)
{
bar = b;
}
};
And finally, here's the usage:
int main()
{
TargetClass* target = new TargetClass(5, 3);
// Works great
typedef Accessor<TargetClass, int, &TargetClass::GetFoo, &TargetClass::SetFoo> fooAcessor;
fooAcessor::Set(target, 13);
int foo = fooAcessor::Get(target);
// Doesn't work, because TargetClass::SetBar takes a const int& as an argument, instead of an int
typedef Accessor<TargetClass, int, &TargetClass::GetBar, &TargetClass::SetBar> barAcessor;
delete target;
return 0;
}
I've tried "overloading" the Acessor struct so it's 4th argument is a const V&, but that doesn't seem to work. Is what I'm trying to do here possible?

If you have access to c++17, and assuming that the proposed standard doesn't change in the meantime, you can have the types deduced automatically:
template <typename F>
struct get_types;
template <typename T, typename V, typename... VP>
struct get_types<V(T::*)(VP...)>
{
using return_type = V;
using class_type = T;
};
template <auto getf, auto setf>
struct Accessor {
using V = typename get_types<decltype(getf)>::return_type;
using T = typename get_types<decltype(getf)>::class_type;
static V Get(T* obj)
{
return (obj->*getf)();
}
static void Set(T* obj, V aValue)
{
return (obj->*setf)(aValue);
}
};
class TargetClass {
int foo;
int bar;
public:
TargetClass(int f, int b)
: foo(f)
, bar(b) {}
int GetFoo() { return foo; }
void SetFoo(int f) { foo = f; }
int GetBar() { return bar; }
void SetBar(const int& b) { bar = b; }
};
int main()
{
TargetClass* target = new TargetClass(5, 3);
using fooAccessor = Accessor<&TargetClass::GetFoo, &TargetClass::SetFoo>;
fooAccessor::Set(target, 13);
int foo = fooAccessor::Get(target);
using barAcessor = Accessor<&TargetClass::GetBar, &TargetClass::SetBar>;
barAcessor::Set(target, 13);
int bar = barAcessor::Get(target);
delete target;
return foo + bar;
}
As of this writing the program above compiles on gcc 7 (snapshot).

You could add another template parameter for the set function's parameter:
template <typename T, typename V, typename VP, V(T::*getf)(), void (T::*setf)(VP)>
And then use for both cases:
typedef Accessor<TargetClass, int, int,
&TargetClass::GetFoo, &TargetClass::SetFoo> fooAcessor;
typedef Accessor<TargetClass, int, const int&,
&TargetClass::GetBar, &TargetClass::SetBar> barAcessor;
Full program:
template <typename T, typename V, typename VP, V(T::*getf)(), void (T::*setf)(VP)>
struct Accessor
{
static V Get(T* obj)
{
return (obj->*getf)();
}
static void Set(T* obj, V aValue)
{
return (obj->*setf)(aValue);
}
};
class TargetClass
{
int foo;
int bar;
public:
TargetClass(int f, int b)
: foo(f)
, bar(b)
{
}
int GetFoo()
{
return foo;
}
void SetFoo(int f)
{
foo = f;
}
int GetBar()
{
return bar;
}
void SetBar(const int& b)
{
bar = b;
}
};
int main()
{
TargetClass* target = new TargetClass(5, 3);
// now has extra int parameter
typedef Accessor<TargetClass, int, int, &TargetClass::GetFoo, &TargetClass::SetFoo> fooAcessor;
fooAcessor::Set(target, 13);
int foo = fooAcessor::Get(target);
// Works now, because TargetClass::SetBar's function parameter was specified explicitly as const int&
typedef Accessor<TargetClass, int, const int&, &TargetClass::GetBar, &TargetClass::SetBar> barAcessor;
barAcessor::Set(target, 13);
int bar = barAcessor::Get(target);
delete target;
return 0;
}

Related

Passing a value caputring lambda to a function which expects a function pointer

I've got a class foo to which I want to pass an object of type T together with a "deleter-like" function with signature void (T). Currently I'm storing this function as an object m_bar of type typedef void (*bar_t)(T); inside foo.
This works without a problem as long as the function I want to use precisely matches the aforementioned signature. However, if the desired function has an additional parameter and I need to pass a specific non-constant value to it, I've tried to pass a lambda function which captures this value by value; but now I'm receiving the compiler error cannot convert from 'initializer list' to 'foo<int>' in the example code below:
`
template<typename T>
struct foo
{
typedef void (*bar_t)(T);
foo(T t, bar_t bar)
: t(t),
bar(bar)
{}
~foo() { bar(t); }
T t;
bar_t bar;
};
void bar1(int x) {}
void bar2(int* x) {}
void bar3(int, int* x) {}
template<typename T, class Bar>
foo<T> make_foo(T t, Bar bar) { return { t, bar }; }
int main()
{
int x = 47, y = 0;
foo f1(x, bar1);
foo f2(x, [](int x) { bar2(&x); });
auto f3a = make_foo(x, [y](int x) { bar3(0, &x); }); // ok
auto f3b = make_foo(x, [y](int x) { bar3(y, &x); }); // compiler error
}
Can we solve this issue without storing a std::function inside in foo?
You basically have 2 choices:
Add extra template parameter:
template<typename T, typename DeleterLike>
struct foo
{
using bar_t = DeleterLike;
foo(T t, bar_t bar)
: t(t),
bar(bar)
{}
~foo() { bar(t); }
T t;
bar_t bar;
};
use some type erasure on the type (as std::function)
template<typename T>
struct foo
{
using bar_t = std::function<void(const T&)>;
foo(T t, bar_t bar)
: t(t),
bar(bar)
{}
~foo() { bar(t); }
T t;
bar_t bar;
};
In the very restricted case where you know y value at compile-time this works:
template <typename T>
struct foo
{
typedef void (*bar_t)(T);
foo(T t, bar_t bar) : t(t), bar(bar) {}
~foo() { bar(t); }
T t;
bar_t bar;
};
template <typename T, typename Y, Y y>
auto create_lambda()
{
return [](T x) { std::cout << x + y << "\n"; };
}
int main()
{
foo<double> f1(1.5, create_lambda<double, int, 1>());
foo<double> f2(1.5, create_lambda<double, int, 2>());
}
and prints
3.5
2.5

How can I build a function concept with a particular signature?

I'm writing some generic software using concepts and I want to check if a particular function symbol name exists with a signature of (void)(int,int) on a struct. To do this I've I'm thinking of approaching this problem through template specialization but I'm sort of lost.
What I want is something to work and through compile time errors if the concept is not satisfied like so:
struct TypeA {
// Passes concept
void process (int a ,int b) const {};
};
struct TypeB {
// Does not pass concept
void process (float a) const {};
};
struct TestConcepts {
/* concept code here */
TestConcepts(T t) {
process_concept(t.process);
};
};
int main(void) {
// Should pass
TestConcept(TypeA{});
// Should throw error
TestConcept(TypeB{});
return 0;
}
I'm having a hard time filling in the blanks but this is what I have so far:
struct TestConcepts {
/* concept code here */
struct process_concept {
process_concept((V*)(IA,IB)){
if (is_integral<IA>::value && is_integral<IB>::value && is_same<V, void>) {
return;
}
static_assert(false, "You must provide function called process of type (void)(int,int)");
};
};
TestConcepts(T t) {
process_concept(&t.process);
};
};
Unfortunately this doesn't work. How can I get this function signature correct?
How about using a function that returns a declared function pointer?
struct TypeA {
// Passes concept
void process (int a ,int b) const {};
};
struct TypeB {
// Does not pass concept
void process (float a) const {};
};
template<typename T>
auto TestConcepts(T) -> void(T::*)(int, int) const
{
return &T::process;
}
int main(void) {
// Should pass
TestConcepts(TypeA{});
// Should throw error
TestConcepts(TypeB{});
return 0;
}
Output:
Error(s):
source_file.cpp: In instantiation of ‘void (T::* TestConcepts(T))(int, int) const [with T = TypeB]’:
source_file.cpp:26:23: required from here
source_file.cpp:19:16: error: cannot convert ‘void (TypeB::*)(float) const’ to ‘void (TypeB::*)(int, int) const’ in return
return &T::process;
^
EDIT: more options
If you want to include void process(long int a, long int b) const; or void process(int a, int b, int c=0) const;, like aschepler is suggesting, you can use type traits.
struct TypeA {
// Passes concept
void process(int a, int b) const {};
};
struct TypeB {
// Does not pass concept
void process(float a) const {};
};
struct TypeC {
// Passes concept
void process(long int a, long int b) const {};
};
struct TypeD {
// Passes concept
void process(int a, int b, int c = 0) const {};
};
struct TypeE {
// Does not pass concept
void process(int a, int b, int c) const {};
};
#include <type_traits>
template<typename T, typename A1, typename A2, typename... An>
typename std::enable_if<
std::is_integral<A1>::value &&
std::is_integral<A2>::value
>::type
TestProcess(const T& t, void(T::*)(A1, A2, An...) const) {
t.process(1, 2);
};
template<typename T>
void TestConcepts(const T& t)
{
TestProcess(t, &T::process);
}
int main(void) {
// Passes
TestConcepts(TypeA{});
// Throws compilation error
TestConcepts(TypeB{});
// Passes
TestConcepts(TypeC{});
// Passes
TestConcepts(TypeD{});
// Throws compilation error
TestConcepts(TypeE{});
return 0;
}

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

Static member function pointer as template argument

I get this compile error with the latest VC++ compiler (Nov 2012 CTP) when using static member function pointer as template argument:
error C2027: use of undefined type 'wrapper<int (int,int),int A::f1(int,int)>'
But when using free function, everything works ok.
I looked up some similar bugs in g++( pointer to static member function is "invalid" as a template argument for g++ ), but there it explicitly states that argument is invalid. What is so different about static functions?
I'm casting the function to void(*)(void) because construct like <typename T_Ret, typename... T_Args, T_Ret(*)(T_Args...)> don't compile for some other urelated reasons.
struct A
{
static int f1(int a, int b)
{
return a + b;
}
};
int f2(int a, int b)
{
return a + b;
}
template <typename Sig, void(*fnc)(void)>
struct wrapper;
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (T_Args...), fnc>
{
static bool apply()
{
// get some ints here
int a = 1;
int b = 2;
typedef T_Ret (fnc_ptr*)(T_Args...);
int res = ( (fnc_ptr)fnc )(a, b);
// do smth with result
res;
return true; // or false
}
};
int main()
{
bool res;
res = wrapper<decltype(A::f1), (void(*)(void))A::f1>::apply(); // error
res = wrapper<decltype(f2), (void(*)(void))f2>::apply(); // compiles ok
return 0;
}
EDIT:
Ok, I narrowed the issue to decltype.
When I write the type explicitly, everything works:
res = wrapper<int(int, int), (void(*)(void))A::f1>::apply(); // compiles ok
EDIT:
Looks like it's a compiler bug: http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/STLCCSeries6#c634886322325940618
Workaround:
Change decltype(A::f1) to decltype(&A::f1) which changed its output from int(int, int) to int (__cdecl *)(int,int). And change
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (T_Args...), fnc>
to
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (*)(T_Args...), fnc>
Working code:
struct A
{
static int f1(int a, int b)
{
return a + b;
}
};
template <typename Sig, void(*fnc)(void)>
struct wrapper;
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (*)(T_Args...), fnc>
{
static bool apply()
{
// get some ints here
int a = 1;
int b = 2;
typedef T_Ret (*fnc_ptr)(T_Args...);
int res = ( (fnc_ptr)fnc )(a, b);
// do smth with result
res;
return true; // or false
}
};
int main()
{
bool res;
res = wrapper<decltype(&A::f1), (void(*)(void))A::f1>::apply();
return 0;
}
You could try something like this:
#include <iostream>
using namespace std;
struct A
{
static int f1(int a, int b)
{
return a + b;
}
};
int f2(int a, int b)
{
return a + b;
}
template <typename T, T X>
struct wrapper
{
template <typename... Args>
static bool value(Args... blargs)
{
return X(blargs...) == 3;
}
};
int main()
{
bool res;
res = wrapper<decltype(&A::f1), &A::f1>::value(1,2);
cout << res << endl;
return 0;
}
But seriously, this is so much easier:
#include <iostream>
using namespace std;
int main()
{
bool res;
res = A::f1(a, b) == 3;
cout << res << endl;
return 0;
}

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;
}