2

I have two templates, one is passed to the other as an argument. I would like to be able to use the Args from the argument in the main template. Or if I have:

template <typename T, typename... Args>
class Foo
{
    typedef T Type;
    static void foo(Args... args)
    {
    }
};

template <typename C>
class Bar
{
    void bar(Args... args)
    {
        // do something
        C::foo(args...);
    }
};

How I can make Args visible in the template Bar. Note that with typedef T Type, I can use C::Type in Bar. What is the syntax if possible for the variadic argument?

gsf
  • 6,612
  • 7
  • 35
  • 64

2 Answers2

4

Here a possible solution based on template template parameter:

template<typename T>
class Bar;

template <template<typename...> class C, typename... Args>
class Bar<C<Args...>> {
    void bar(Args... args) {
        // do something
        C<Args...>::foo(args...);
    }
};

You can use it as it follows:

Bar<Foo<int, double>> v;

You don't get the arguments Args directly from the C class. Instead, the idea is to exploit the fact that the C class is a variadic templated one for itself, thus getting Args from the parameter list of a template specialization of Bar.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • this does not answer the question, but it is better option from what I was trying to do - I will mark it as solution – gsf Apr 25 '16 at 21:28
  • @gsf Well, actually this way you are *able to use the Args from the argument in the main template*. So, it also answers the question indeed. ;-) – skypjack Apr 25 '16 at 21:30
1

You could have a typedef for a 'type list' that wraps Args.... Here's an example using tuple to perform the role of the type list:

#include <tuple>
#include <experimental/tuple>

template <typename T, typename... Args>
class Foo
{
public:
    using Type = T;

    using Arguments = std::tuple<Args...>;

    static void foo(Args... args)
    {
    }
};

template <typename C>
class Bar
{
public:
    void bar(typename C::Arguments &&args)
    {
        // do something
        std::experimental::apply(C::foo, args);
    }
};

int main() {
    Bar<Foo<int, double, float>> b;
    b.bar(std::make_tuple(2.0, 1.0f));
}

With a bit more meta-programming it should be possible to produce a Bar::bar function that takes arguments directly based on C::Arguments.

bames53
  • 86,085
  • 15
  • 179
  • 244