I apologize already having asked a similar question here when I should have modified the question I asked first.
I have the class Level
which constructor requires an argument.
Using variadic templates I create a type LevelType
for a member of the class Tree
which is a tuple of elements of type Level
.
How can I avoid repeating the value data
in the initialization list of Tree
?
As a further constraint, it should be possible for objects of class Tree
to be constructed at compile time, so as far as I know I need some kind of template metaprogramming-fu.
Thank you!
Here's a code snippet:
#include<utility>
#include<array>
#include<iostream>
class LevelData
{};
template <typename LevelType>
class Level
{
public:
Level(LevelData & data_):
data(data_)
{};
LevelData & data ;
};
template <std::size_t nLevels,typename LevelType>
class Tree
{
public:
Tree(LevelData & data):
level(data,data,data,data,data)
{};
LevelType level ;
};
template <std::size_t nLevels,auto... Is>
auto make_tree_impl(std::index_sequence<Is...>)
-> Tree<nLevels,std::tuple<Level<std::array<double, std::size_t{1} << Is>>...>>;
template <std::size_t nLevels>
using make_tree = decltype(make_tree_impl<nLevels>(std::make_index_sequence<nLevels>{}));
int main()
{
const unsigned int nLevels = 5;
LevelData data;
auto tree = make_tree<nLevels>(data);
std::cout << std::is_same<decltype(tree),
Tree<nLevels,std::tuple<Level<std::array<double,1>>,
Level<std::array<double,2>>,
Level<std::array<double,4>>,
Level<std::array<double,8>>,
Level<std::array<double,16>>>>>::value << std::endl ;
return 0;
}
You could make use of make_index_sequence
again, only this time it's used to repeat data
as many times as you have types in your tuple
.
Unfolding can be done by using (static_cast<void>(Is), data)...
since the left part of the ,
operator will be discarded, leaving only data
, sizeof...(Is)
number of times.
template <std::size_t nLevels, typename LevelType>
class Tree {
public:
Tree(LevelData& data)
: level{[&]<std::size_t... Is>(std::index_sequence<Is...>) {
return LevelType{(static_cast<void>(Is), data)...};
}(std::make_index_sequence<std::tuple_size_v<LevelType>>())} {}
LevelType level;
};