So, I've recently build a delegate system using c++11's variadic templates, and it works just as a charm.
However in the system I've built arguments to functions are given at creation-time (as I'd like), but now I'd also like to be able to pass some (variable) number of arguments at call-time. In order to achieve this, I went and redid my code, however is where I'm getting the issues;
error: parameter packs must be at the end of the parameter list
sorry, unimplemented: cannot expand ‘Arguments ...’ into a fixed-length argument list
error: type/value mismatch at argument 1 in template parameter list for ‘template<<declaration error>, class ... Params> class FunctionDelegate’
... and a lot more to come, so here's a snippet that spawned the issue;
template<typename... Params>
class Runnable
{
public:
virtual void invoke(tuple<Params...> params) = 0;
virtual ~Runnable()
{
}
};
This is the parent class for my two delegates (FunctionDelegate and ObjectDelegate). This used to be an untemplated class (as invoke didn't take any arguments), however as I've a variadic template list to it, I had to modify my subclasses as well (obviously), and I've just added another variadic template to them;
template<typename... Arguments, typename... Params>
class FunctionDelegate : public Runnable<Params...>
{
public:
typedef void (*FunctionType)(Arguments..., Params...);
FunctionDelegate(FunctionType function, tuple<Arguments...> args)
: function(function), args(args)
{
}
void invoke(tuple<Params...> params)
{
callFunction(typename gens<sizeof...(Arguments)>::type(), params, typename gens<sizeof...(Params)>::type());
}
private:
template<int... S, int... R>
void callFunction(seq<S...>, tuple<Params...> params, seq<R...>)
{
function(get<S>(args)..., get<R>(params)...);
}
private:
FunctionType function;
tuple<Arguments...> args;
};
This however, does not seem to be allowed, atleast that's what I suspect, so;
Any help or insight is welcome.
No, you cannot use such code. You can use following for example
template<typename... Params>
class FunctionDelegate;
or
template<typename Arguments, typename Params>
class FunctionDelegate;
as Xeo suggests.
template<typename... Arguments, typename... Params>
class FunctionDelegate<tuple<Arguments...>, tuple<Params...>> :
public Runnable<Params...> { // };
Concerning your first two questions (the answers are "No" and "No"), paragraph 14.1/11 of the C++11 Standard specifies:
If a template-parameter of a class template or alias template has a default template-argument, each subsequent template-parameter shall either have a default template-argument supplied or be a template parameter pack. If a template-parameter of a primary class template or alias template is a template parameter pack, it shall be the last template-parameter. A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced or has a default argument (14.8.2). [ Example:
template<class T1 = int, class T2> class B; // error
// U cannot be deduced or specified
template<class... T, class... U> void f() { }
template<class... T, class U> void g() { }
—end example ]
Your example clearly violates the sentence in bold, which prohibits having more than one template argument pack on a (primary) class template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With