3

Before I describe the problem I will give you an idea what is the target of my work.

I want to have a template which creates a class ( while do this unrolling a typelist recursively) which derives from all given types in a variadic list of parameters. That works fine. (see below)

Now is my target to provide all parameters to all constructors of the subclasses via an "automatic" created type from the unrolling template. Finally each of the Unroll classes should eat the parameters it needs to create a instance of the given classes. Each of the recursively created template instances should eat one of the parameter packs contained in the TypeContainer.

Before you ask: This code is only academic to learn new features of c++11. :-)

// create a wrapper around tuple to make it constructible with initializer list
template <typename ... T>
class TypeContainer: std::tuple<T...>
{
    public:
        TypeContainer(T... args):std::tuple<T...>(args...){};
};

// create a template to concatenate some typelists
// ??? is there a already usable template in std:: ??? 
template < typename ... X >
class TypeConcatenate;

template <typename T, typename ... S >
class TypeConcatenate < T, TypeContainer< S... >>
{
    public:
        typedef TypeContainer< T, S...> type;
};

// The follwing template unrolls a typelist and creates a recursively 
// inherited class.

template <typename ... T> class Unroll;

template < class Base, class Head, class ... Next >
class Unroll< Base, Head, Next...>: public Unroll < Base, Next...>
{
    public:
        // collect all needed types for the instance creation of all child
        // classes.
        typedef typename TypeConcatenate<typename Head::Parms, typename Unroll < Base, Next...>::AllParms>::type AllParms;

};

template < class Base, class Head>
class Unroll < Base, Head> 
{
    // provide first parameter set for the constructor 
    public:
        typedef TypeContainer<typename Head::Parms> AllParms;
};

template < class Base, class ... Next>
class Top : public Unroll < Base, Next...>
{ 
    // I want to have a constructor which accepts
    // all parameters for all the sub classes.
    public:
        template <typename ...T> Top(T... args);
};  

// ??? The following lines of code will not compile!!!
// gcc 4.8.1 gives:
// error: ISO C++ forbids declaration of 'Top' with no type
// ??? Why the compiler could not interpret this as constructor ???
template <typename Base, typename ... Next, typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}

class Base {};
class A: public Base
{
    public: 
        typedef TypeContainer<int, float> Parms;

        A( int i, float f){}
} ;
class B: public Base
{
    public:
        typedef TypeContainer< char, int> Parms;
        B( char c, int i){}
};

Top<Base, A, B> top  {A{ 1,1},B{1,1}};

Questions:

1) Is there maybe a simpler way to determine the parameter list for the class hierarchy. My way with typedef typename TypeConcatenate<typename Head::Parms, typename Unroll < Base, Next...>::AllParms>::type AllParms; looks a bit hard :-)

2) Because of 1) I have a kind of type container which holds T... and the problem with my constructor arise with the unpacking of the parameter list which is contained in a container. Maybe my solution is much to complex. Nay hint to solve the basic idea?

3) Ignoring that the problems of 1) and 2) are comes from a totally boring design I want to know which I couldn’t specialize the constructor with

template <typename Base, typename ... Next, typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}

For any further discussion: Yes, I know that the parameters should be forwarded and not given as value an so on. But I want to simplify the example which seems long enough for the discussion.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
Klaus
  • 24,205
  • 7
  • 58
  • 113
  • 1
    In case you're curious, you can concatenate `std::tuple`s with http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat – Nate Kohl Aug 12 '13 at 15:04
  • Your implementation basically ignores the first parameter of `Top` - `Base` - is that intentional? – Casey Aug 12 '13 at 15:20
  • No, that was not intentional, that is a copy and paste mistake :-) The given example is a shrink from the original source. – Klaus Aug 12 '13 at 15:45

1 Answers1

1

It sounds like you want a variadic forwarding constructor, something like:

template <typename... Ts>
class lots_of_parents : public Ts...
{
public:
    template <typename... Args>
    lots_of_parents(Args&&... args) : Ts(std::forward<Args>(args))... {}
};

lots_of_parents<A, B> mytop {A{1, 1}, B{1, 1}};

and either (a) the rest of the question is XY problem, or (b) I'm simply not understanding.

EDIT: Missed the question about your constructor. Ignoring for the moment that functions cannot be partially specialized, I think the syntax would look like:

template <typename Base, typename ... Next>
template <typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}

Which still doesn't really make sense, there's no way to deduce TypeContainer<T...> from T... args.

Casey
  • 41,449
  • 7
  • 95
  • 125
  • What I want is not the variadic forwarding constructor because the classes should be derived in a chain making the lowest class attributes visible to all the higher ones. The second part of the answer gives me the hint to a different syntax but fails also. The error message is still the same: ISO C++ forbids declaration of 'Top' with no type – Klaus Aug 12 '13 at 15:48