Yan Zhu
Yan Zhu

Reputation: 4346

How to create a template class with N different types of variable members so that

Here is what I want to achieve:

A template class, it has N variable members, each of them may have different type. Also this class can get N functions/functors outside so that each functor will update a member variable with corresponding type. Ideally, I would like N is unknown, which means we need Variadic template.

Here is an example for N=2 (I ideally I would like it to be functor instead of function, but I also have some difficulty there.)

template<typename T1, typename T2>
class TwoInput
{
public:
    TwoInput(T1 (*f1)(), T2 (*f2)()) : _f1(f1), _f2(f2) {};
    void run(){
    t1 = (*_f1)();
    t2 = (*_f2)();
    };
    void output(){std::cout<<_t1<<std::endl; std::cout<<_t2<<std::endl;};
protected:
    T1 _t1;
    T2 _t2;
    T1 (*_f1)();
    T2 (*_f2)();
};

Upvotes: 0

Views: 128

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

Start with std::tuple of your data.

Then mutate the types to create a std::tuple of functions.

Then write a function to apply the std::tuple of functions to the std::tuple of data.

#include <utility>

template< template<typename>class Typemap, typename Tuple>
struct map_types;
template< template<typename>class Typemap, template<typename...>class pack, typename... Args>
struct map_types< Typemap, pack<Args...> > {
  typedef pack< Typemap<Args>... > type;
};

template< template<typename>class Typemap, typename Tuple>
using MapTypes = typename map_types<Typemap, Tuple>::type;

template< typename T >
using NullaryFuncReturning = T(*)();

template<int...> struct seq {};
template<int max, int... s> struct make_seq:make_seq<max-1, max-1, s...> {}:
template<int... s> struct make_seq<0,s...>:seq<s...> {};

void do_in_order() {}
template<typename F0, typename... Fs>
void do_in_order( F0&& f0, Fs&&... fs ) {
  std::forward<F0>(f0)();
  do_in_order( std::forward<Fs>(fs)... );
}

template< int... s, typename Funcs, typename Data >
void pairwise_apply_helper( seq<s...>, Funcs&& funcs, Data&& data ) {
  do_in_order( [&]{ std::get<s>(data) = std::get<s>( funcs )() }... );
}
template< typename... Funcs, typename... Data >
void pairwise_apply( std::tuple<Funcs...> funcs, std::tuple<Data...>& data ) {
  pairwise_apply_helper( make_seq<sizeof...(Funcs)>, std::move(funcs), data );
}

typedef std::tuple<int, double, int> data_type;
MapTypes< NullaryFuncReturning, data_type > func_type;

int seven() { return 7; }
double approx_pi() { return 3.14; }

data_type data;
func_type func{seven, approx_pi, seven};
#include <iostream>
int main() {
  pairwise_apply( func, data );
}

or something like that (untested, I need to go to bed).

Upvotes: 2

Related Questions