Let's assume we have something like this: An Interface for some class Foo ( 'FooInterface' ) and a container class Bar that contains derived classes from 'FooInterface'.
Now I forward a typelist of the types of the derived classes ( 'FooOne', 'FooTwo' ) to the container class and it stores an instance of them in a 'boost::hana::tuple' subsequent to a small type computation ( 'FooTuple' ).
Now how do I initialize the tuple elements with a dereferenced this-pointer, depending on the size of 'FooList' ?
#include <iostream>
#include <boost/hana.hpp>
namespace hana = boost::hana;
template <typename FooList>
class Bar;
template <typename FooList>
class FooInterface
{
public:
FooInterface(Bar<FooList>& bar) {}
public:
virtual void foo() = 0;
};
class FooOne;
class FooTwo;
using MyFooList = decltype(hana::tuple_t<FooOne, FooTwo>);
class FooOne final
: public FooInterface<MyFooList>
{
public:
FooOne(Bar<MyFooList>& bar)
: FooInterface(bar)
{}
public:
void foo() override
{
std::cout << "FooOne!\n";
}
};
class FooTwo final
: public FooInterface<MyFooList>
{
public:
FooTwo(Bar<MyFooList>& bar)
: FooInterface(bar)
{}
public:
void foo() override
{
std::cout << "FooTwo!\n";
}
};
template <typename FooList>
class Bar
{
public:
using FooTuple = typename decltype(hana::unpack(FooList(), hana::template_<hana::tuple>))::type;
FooTuple foos{ *this, *this };
};
int main()
{
Bar<MyFooList> b;
b.foos[hana::int_c<0>].foo();
b.foos[hana::int_c<1>].foo();
}
Output :
FooOne!
FooTwo!
hana::replicate
is your friend.
template <typename FooList>
class Bar {
...
using FooTuple = ...;
FooTuple foos;
Bar() : foos(hana::replicate<hana::tuple_tag>(*this, hana::size_c<N>)) {}
};
Now, you have to be careful cause that'll make a copy of each *this
when creating a tuple in replicate
. If you want references instead, use reference_wrapper
like this:
foos(hana::replicate<hana::tuple_tag>(std::ref(*this), hana::size_c<N>))
and then make sure that the constructor of each thing in FooTuple
can be constructed from a reference_wrapper
(which is the case if they take a reference).