1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
#include <iostream>
#include <vector>
#include <tuple>
// step-1: make the sequence U<T,0>, U<T,1>,..., U<T,N>
template<typename... Arg>
struct Sequence { using Tuple = std::tuple<Arg...>; };
//
template<typename S, typename LastArg>
struct PushBackArg;
template<typename... Arg, typename LastArg>
struct PushBackArg<Sequence<Arg...>, LastArg> { using type = Sequence<Arg..., LastArg>; };
//
template<template<typename,int> typename GenericArg, typename T, int N>
struct MakeSequence { using type = typename PushBackArg<typename MakeSequence<GenericArg,T,N-1>::type, GenericArg<T,N> >::type; };
template<template<typename,int> typename GenericArg, typename T>
struct MakeSequence<GenericArg,T,0> { using type = Sequence< GenericArg<T,0> >; };
// step-2: access and change std::tuple members
template<typename T>
constexpr std::make_index_sequence<std::tuple_size<T>::value>
get_indexes_(T const& )
{ return {}; }
//
template<typename Func, typename...Arg, std::size_t...idx>
void for_each_in_tuple(std::tuple<Arg...> &tup, Func func, std::index_sequence<idx...>)
{
using expander = int[];
(void)expander { 0, ((void)func(std::get<idx>(tup)), 0)... };
}
template<typename Func, typename...Arg>
void for_each_in_tuple(std::tuple<Arg...> &tup, Func func)
{
for_each_in_tuple(tup, func, std::make_index_sequence<sizeof...(Arg)>());
}
// step-3: define the C class
template<template<typename,int> typename GenericArg, typename T, int N>
class C
{
private:
typedef typename MakeSequence<GenericArg,T,N>::type::Tuple Tuple;
Tuple tup_;
public:
C()
{
std::cout << "call C<T, " << N << ">::C()\n";
std::cout << "std::tuple_size<Tuple>::value = " << std::tuple_size<Tuple>::value << '\n';
}
void update()
{
std::cout << "call C<T, " << N << ">().update()\n";
for_each_in_tuple(tup_, [](auto &arg) { arg.update(); });
}
template<int idx>
const GenericArg<T,idx> &arg() const
{ return std::get<idx>(tup_); }
};
// step-4: define the U class
template<typename T, int idx>
class U
{
public:
U()
{
std::cout << "call U<T, " << idx << ">::U()\n";
}
void update()
{
std::cout << "call U<T, " << idx << ">().update()\n";
}
};
//
class Dummy;
//
int main()
{
enum { N = 2 }; // compile-time parameter
// step-1: instanciate C
C<U,Dummy, N> c0;
std::cout << "\n";
// step-2: access C members and update
c0.update();
std::cout << "\n";
#if 1
// step-3: vector of C<N> objects
int M = 4; // run-time variable
std::vector< C<U,Dummy, N> > cVector(M);
std::cout << "\n";
std::cout << "update all vector's elements\n";
for(int mIdx = 0; mIdx < M; ++mIdx) {
std::cout << "mIdx = " << mIdx << "\n";
cVector[mIdx].update();
}
#endif
return 0;
}
|