Metaprogramming template recursion doesn't recurse (edited important) - c++

I try to invoke function void set (...) recursively using metaprogramming.
The problem is that it seems to invokes only once.
template <int N>
struct GEN
{
enum {value = GEN<N-1>::value};
template <typename T>
static inline void set(T& tup, int l_item)
{
cout<<"item value: "<<l_item<<", N-1: "<< N-1 << ", value: "<<value <<endl;
typedef typename boost::tuples::element<N-1, T>::type _el_type;
get<N-1>(tup) = atomic_item<N-1, _el_type>(l_item);
};
};
template<>
struct GEN<0>
{
enum {value = 0};
template <typename T>
static inline void set(T& tup, int l_item)
{
typedef typename boost::tuples::element<0, T>::type _el_type;
get<0>(tup) = atomic_item<0, _el_type>(l_item);
};
};
main(){
....
/** this is how i try to invoke it */
GEN<3>::set(w,1);
}
Output:
item value: 1, N-1: 2, value: 0
function has been invoked only once...
EDIT
is there a way to do kind of loop with for_each or anything else to get something simmilar:
for_each<range_c<int,0,3> f{operator()(T i)GEN<typename T::value>::set(w,1)}>
or something similar to achieve invoke for all of those elements?
Particularly I'd like to have this:
GEN<3>::set(w,1);
GEN<2>::set(w,1);
GEN<1>::set(w,1);
In loop.

There is no recursion. Recursion means calling yourself. The set function in your code does not do this.
Your value declaration does recurse (i.e. GEN<N>::value is defined in terms of GEN<N -1>::value) – but in a pretty uninteresting way, it just propagates the base case value, 0 – and furthermore you don’t seem to be using this value anyway.
/EDIT: Here’s a very simple example to address the point raised by you in the comments, i.e. to achieve the effect of
GEN<3>::set(w,1);
GEN<2>::set(w,1);
GEN<1>::set(w,1);
That’s actually pretty easy:
template <unsigned N>
struct GEN {
template <typename T>
static void set(T& w, int value) {
// Do something, e.g.:
get<N - 1>(w) = value;
// Recurse:
GEN<N - 1>::set(w, value);
}
};
template <>
struct GEN<0> {
template <typename T>
static void set(T&, int) { /* empty */ }
};
Now you can call this code via GEN<3>::set(w, 1) and it will have the desired semantics.

The metaprogramming template obviously did recurse since your code compiled and ran.
Were you expecting a recursive call of the set function? The function you called, GEN<3>::set doesn't call the set function of any other class, so there is no run-time recursion. There is only compile-time recursion to instantiate the templates. But compile-time recursion doesn't generate output at run time.

Related

Is there a way to call a function multiple times on the reference it returns programmatically? -Tuple Dynamic access

Out of interest I am trying to implement a variadic template tuple type with dynamic access and I would like to avoid casts and returning boost::any or boost::variant. I have come to the point were every recursive inheritance stores a pointer to itself and I am able to return it like so:
ParentType& next() {
return *this;
}
I can call this when I write in source and iterate like so for example:
MyTupleImpl<int, std::string, float> myTuple;
myTuple.next().next().next();
which returns a
MyTupleImpl<float> &
I can then do some operations on the data held by this Tuple like so:
void DoSomething( myTuple.next().next().next().data);
I can write this down in source, but how could I implement it such that I just pass a number n and it applies the function next() n times on its returned reference.
I tried recursion along the lines of:
ParentType* get(int i, int j, OwnType k) {
std::cout << "j" << j << "i" << i << std::endl;
if (j < i) {
j++;
return k.next().get(i, j, k.next());
}
else
{
return k.current;
}
}
As is relatively obvious there is always a conflict with the return type of the function since the context in which its called like so:
myTuple.get(1,0,myTuple);
has its ParentType set but when next is called ParentType changes.
I can imagine that return Type deduction is one of the reasons why tuples can not be dynamically accessed. However why does the this work programmatically when I call in source.
myTuple.next().next();
for example.
I know this is somewhat confused however I hope some of you will understand what I mean and be able to help me. I apologize as I am somewhat of a Novice when it comes to C++ and templated classes.
I'm assuming the following bare-bones definitions for MyTuple:
template <class...>
struct MyTuple;
template <class Head, class... Tail>
struct MyTuple<Head, Tail...> : MyTuple<Tail...> {
Head data;
};
template <class T>
struct MyTuple<T> {
T data;
};
We can take advantage of their recursive nature to define a get(i) function on each layer, that will either "return" its data if i == 0, and pass the call over to the next layer otherwise.
Since we can't (or rather, don't want to) cram N different types into the return value, let's flip the flow control on its head: instead of having get return a reference and use it afterwards, we'll pass "use it afterwards" as an overloaded functor to get, which will call the correct overload.
template <class Head, class... Tail>
struct MyTuple<Head, Tail...> : MyTuple<Tail...> {
MyTuple<Tail...> &next() {
return *this;
}
template <class F>
auto get(std::size_t i, F &&f) {
return i
? next().get(i - 1u, std::forward<F>(f))
: std::forward<F>(f)(data);
}
Head data;
};
template <class T>
struct MyTuple<T> {
template <class F>
auto get(std::size_t i, F &&f) {
assert(!i);
return std::forward<F>(f)(data);
}
T data;
};
The return value of get is the return value of the selected overload. Its type is the common type (as std::common_type would return) of all of the involved overloads. Using it looks like this:
MyTuple<float, int, double> tup;
struct {
void operator()(float) const { }
void operator()(int) const { }
void operator()(double) const { }
} func;
for(std::size_t i = 0; i < 3; ++i)
tup.get(i, func);
Each iteration of the loop will call the corresponding overload with the required data.
See it live on Coliru
why does the this work programmatically when i call in source.
myTuple.next().next();
Because the type is known at compile time. There are no runtime arguments, like in your get(int i, int j, OwnType k) attempt. Your attempt cannot possibly work, but following would be possible to implement:
template<class... Ts>
template<std::size_t I>
magic_type& MyTupleImpl<Ts...>::get();
// magic_type is not actual code. It is a
// placeholder for a proper implementation
Template arguments are known at compile time, so this can work. Now we must use template magic to figure out the correct type to return. You'll need to use a recursive helper template similar to the following (this example is modified from cppreference):
template< std::size_t I, class T >
struct tuple_element;
// recursive case
template< std::size_t I, class Head, class... Tail >
struct tuple_element<I, MyTupleImpl<Head, Tail...>>
: tuple_element<I-1, MyTupleImpl<Tail...>> { };
// base case
template< class Head, class... Tail >
struct tuple_element<0, MyTupleImpl<Head, Tail...>> {
typedef Head type;
};
With the help of this, we could declare:
template<class... Ts>
template<std::size_t I>
typename tuple_element<I, Ts...>::type&
MyTupleImpl<Ts...>::get();
I'll leave the implementation of MyTupleImpl::get as an exercise.
Warning: No code in this answer has been tested in any way.

Call sequence of template function for sequence of template parameters

Let's imagine I have several template functions, e.g.:
template <int I> void f();
template <int I> void g();
template <int I> void h();
How can I call sequence of any of these functions for sequence of template parameters?
In other words, I need such behaviour:
{some template magic}<1, 5>(f); // This is pseudocode, I don't need exactly this format of calling.
unrolls into:
f<1>();
f<2>();
f<3>();
f<4>();
f<5>();
And I need the same method to work for every of my functions (not only for f, but for g and h too) without writing big awkward structure for every of these functions.
I can use C++11, and even already implemented in latest development gcc version C++1y/C++14 functionality (http://gcc.gnu.org/projects/cxx1y.html), e.g. polymorphic lambdas.
With C++1y features. Instead of calling the function directly and passing the template argument as, well, a template argument, you can create a lambda that takes a function argument which contains the template argument as part of its type. I.e.
f<42>();
[](std::integral_constant<int, 42> x) { f<x.value>(); }
[](auto x) { f<x.value>(); }
With this idea, we can pass the function template f around, when wrapped into such a polymorphic lambda. That's possible for any kind of overload set, one of the things you can't do with ordinary lambdas.
To call f with a sequence of template arguments, we'll need the common indices classes for the indices expansion trick. Those will be in the C++1y Standard Library. Coliru's clang++ compiler for example still uses an older libstdc++ which doesn't have them AFAIK. But we can write our own:
#include <utility>
using std::integral_constant;
using std::integer_sequence; // C++1y StdLib
using std::make_integer_sequence; // C++1y StdLib
// C++11 implementation of those two C++1y StdLib classes:
/*
template<class T, int...> struct integer_sequence {};
template<class T, int N, int... Is>
struct make_integer_sequence : make_integer_sequence<T, N-1, N-1, Is...> {};
template<class T, int... Is>
struct make_integer_sequence<T, 0, Is...> : integer_sequence<T, Is...> {};
*/
When we write make_integer_sequence<int, 5>, we'll get a type that's derived from integer_sequence<int, 0, 1, 2, 3, 4>. From the latter type, we can deduce the indices:
template<int... Indices> void example(integer_sequence<int, Indices...>);
Inside this function, we have access to the indices as a parameter pack. We'll use the indices to call the lamba / function object f as follows (not the function template f from the question):
f( integral_constant<int, Indices>{} )...
// i.e.
f( integral_constant<int, 0>{} ),
f( integral_constant<int, 1>{} ),
f( integral_constant<int, 2>{} ),
// and so on
Parameter packs can only be expanded in certain contexts. Typically, you'd expand the pack as initializers (e.g. of a dummy array), as the evaluation of those is are guaranteed to be ordered (thanks, Johannes Schaub). Instead of an array, one could use a class type such as
struct expand { constexpr expand(...) {} };
// usage:
expand { pattern... };
A dummy array looks like this:
int expand[] = { pattern... };
(void)expand; // silence compiler warning: `expand` not used
Another tricky part is to deal with functions returning void as the pattern. If we combine a function call with a comma operator, we always get a result
(f(argument), 0) // always has type int and value 0
To break any existing overloaded comma operators, add a void()
(f(argument), void(), 0)
Finally, combine all the above to create magic:
template<int beg, class F, int... Is>
constexpr void magic(F f, integer_sequence<int, Is...>)
{
int expand[] = { (f(integral_constant<int, beg+Is>{}), void(), 0)... };
(void)expand;
}
template<int beg, int end, class F>
constexpr auto magic(F f)
{
// v~~~~~~~v see below (*)
return magic<beg>(f, make_integer_sequence<int, end-beg+1>{});
}
Usage example:
#include <iostream>
template<int N> void f() { std::cout << N << "\n"; }
int main()
{
//magic<1, 5>( [](auto x) { f<decltype(x)::value>(); } );
magic<1, 5>( [](auto x) { f<x.value>(); } );
}
(*) IMHO end-beg+1 is bad practice. There's a reason why the StdLib works with half-open ranges of the form [begin, end): The empty range simply is [begin, begin). With the StdLib using half-open ranges, it might be inconsistent to use closed ranges here. (There's one exception in the StdLib I know of, it has to do with PRNGs and the maximum integer value.)
I'd suggest you'd design your magic interface to take half-open ranges, i.e.
magic<1, 6>( [](auto x) { f<x.value>(); } ); // [1, 6) i.e. {1,2,3,4,5}
with the implementation
template<int beg, int end, class F>
constexpr auto magic(F f)
{
// v~~~~~v
return magic<beg>(f, make_integer_sequence<int, end-beg>{});
}
Note the weird +1 disappears.
Using reified functions and template template arguments:
#include <iostream>
template<int I> class f {
public:
static void call() {
std::cout << I << '\n';
}
};
template<template<int I> class X, int I, int J> class magic {
public:
static void call() {
X<I>::call();
magic::call();
}
};
template<template<int I> class X, int I> class magic<X,I,I> {
public:
static void call() {
X<I>::call();
}
};
int main(int argc, char** argv) {
magic<f,2,6>::call();
return 0;
}

Function array initialization at compile time with metaprograming

In video-games is common that resources are loaded in a step fashion way, so within a single thread a loading bar can update at each loading step. By example:
1 -> Load texture A
2 -> Update Loading Bar to 2%
3 -> Load texture B
4 -> Update Loading Bar to 4%
5 ...
This can be done in many ways. One of these is define a function for each loading step.
void LoadTextureA()
{
//Loading routine
...
}
This has the advantage of readability, not need too much nested code and even possible in some cases to share loading routines between two game states.
Now what I was thinking was to generalize this "function-for-step" model with templates. Lets say.
template <int S>
struct Foo{
void LoadingStep()
{
}
};
template <>
struct Foo<0>
{
void LoadingStep()
{
//First loading step
...
}
};
Please correct me if I'm wrong. But it appears possible that I can compile-time iterate through 0 .. to N steps using metaprogramming and assign this specialized functions to an array or vector of function pointers.
N steps are known at compile time along with it respective functions.
Function pointer vector would be iterated like this:
template <int Steps>
class Loader {
public:
bool Load()
{
functionArray[m_step]();
if (++m_step == Steps)
return false; //End loading
else
return true;
}
private:
int m_step;
}
Is this possible? I know that that are easier ways to do it. But besides project requirments it's an interesting programming challenge
I achieved it based on Kal answer of a similar problem
Create N-element constexpr array in C++11
template <int S>
struct Foo{
static void LoadingStep()
{
}
};
template <>
struct Foo<0>
{
static void LoadingStep()
{
//First loading step
}
};
template<template<int S> class T,int N, int... Rest>
struct Array_impl {
static constexpr auto& value = Array_impl<T,N - 1, N, Rest...>::value;
};
template<template<int S> class T,int... Rest>
struct Array_impl<T,0, Rest...> {
static constexpr std::array<void*,sizeof...(Rest)+1> value = {reinterpret_cast<void*>(T<0>::LoadingStep),reinterpret_cast<void*>(T<Rest>::LoadingStep)...};
};
template<template<int S> class T,int... Rest>
constexpr std::array<void*,sizeof...(Rest)+1> Array_impl<T,0, Rest...>::value;
template<template<int S> class T,int N>
struct F_Array {
static_assert(N >= 0, "N must be at least 0");
static constexpr auto& value = Array_impl<T,N>::value;
F_Array() = delete;
F_Array(const F_Array&) = delete;
F_Array(F_Array&&) = delete;
};
Using example:
int main()
{
auto& value = F_Array< Foo ,4>::value;
std::cout << value[0] << std::endl;
}
This yields of void* array of pointers to template functions:
Foo<0>::LoadinStep()
Foo<1>::LoadinStep()
Foo<2>::LoadinStep()
Foo<3>::LoadinStep()
Foo<4>::LoadinStep()
Since Foo<1..3> are not specialized they will fall to Default LoadingStep function
Yes. It's possible. And if you use the template metaprogramming, you don't need to use a run time loop, but a recursive call to a template method:
#include <iostream>
// The template numerated methods
template <int S> struct Foo{static void LoadingStep(){}};
template <> struct Foo<0> {static void LoadingStep(){std::cout<<0;}};
template <> struct Foo<1> {static void LoadingStep(){std::cout<<1;}};
template <> struct Foo<2> {static void LoadingStep(){std::cout<<2;}};
// The loader template method
template <int Step>
void Loader()
{
Foo<Step>::LoadingStep();
Loader<Step-1>();
}
// Stopping rule
template <> void Loader<-1>(){}
int main()
{
Loader<2>();
}
If you want an array:
LoadingFunction functionArray[] = {Function0, Function1, Function2};
.....
for (int i = 0; i < nSteps; ++i)
RunStep(i, nSteps, Function[i]);
Or initialize an std container with it.
If you want templates, you could write
for (int i = 0; i < nSteps; ++i)
RunStep(i, nSteps, Function<i>);
except i in Function<i> must be a constant. So you have to do it with a templated recursive something:
template <int i, int NSteps> struct RunSteps
{
void Run()
{
RunStep(i, NSteps, Function<i>);
RunSteps<i+1, NSteps>::Run();
}
};
template <int NSteps> struct RunSteps<NSteps, NSteps>
{
void Run() {}
};
RunSteps<0, NSteps>::Run();
Compile-time iteration doesn't really exist. The for loop and the templated recursive something do exactly the same thing. The compiler is as capable of unrolling a loop, as of inlining a call.
It looks like there's very little to be gained from templatizing this stuff, and lots to lose.
It is not clear why you would want to put templated functions to an array at compile time, but here you go:
LoadingFunction functionArray[] = {Function<0>, Function<1>, Function<2>};
Now if you don't want to enumerate functions manually like that, it could be a bit of a challenge. It doesn't seem possible with either legacy C arrays or any of the std containers. Assuming you really need it, it's possible to write a custom container capable of such initialization.
template <template <int> class FunctionWrappper, int NFunctions>
class MyOptimizedFunctionArray {
// filling this space is left as an exercise
};

compile-time counter for template classes

Imagine that you have a lot of classes with a lot of different template parameters. Every class has a method static void f(). You want to collect all these function pointers in a list L.
A run-time solution would be easy:
typedef void (*p)();
std::vector<p> L;
int reg (p x) { static int i = 0; L.push_back(x); return i++; } // also returns an unique id
template <typename T> struct regt { static int id; };
template <typename T> int regt<T>::id = reg (T::f);
template < typename ... T > struct class1 : regt< class1<T...> > { static void f(); };
template < typename ... T > struct class2 : regt< class2<T...> > { static void f(); };
// etc.
The compiler knows all f()s of all instantiated classes at compile-time. So, theoretically it should be possible to generate such a list (a const std::array<p, S> L with some S) as a compile-time constant list. But how? (C++0x solutions are welcome, too).
Why do I need this?
On an architecture with only 256 kB (for code and data), I need to generate objects for incoming ids of classes. Existing serialization frameworks or the run-time solution above are unnecessarily big. Without templates a compile-time solution would be easy, but I want to keep all the advantages templates offer.
Manually
The simplest thing that you can do is just roll the code manually, I don't think that there is much that can be used to your advantage from the templates, so I will use plain classes, where A, B... stand for particular instantiations of your types. That allows for compile time initialization of the types, at the cost of having to remember to update the lookup table whenever a new type is added to the system:
typedef void (*function_t)();
function_t func[] = {
&A::f,
&B::f,
&C::f
};
I would recommend this, from a maintenance point of view. Automating the system will make the code much harder to understand and maintain in the future.
Macros
The simple most automated one, which will probably generate less code is a macro generation system is just using macros. Since this first approach will use extensive use of macros, I will generate the functions automatically, as you did in the previous question. You can remove that part of code if you have (hopefully) given up the path of full code generation through macros.
To avoid having to retype the names of the types in different contexts you can define a macro with all the data you need for any context, and then use other macros to filter what is to be used (and how) in each particular context:
// This is the actual list of all types, the id and the code that you were
// generating in the other question for the static function:
#define FOREACH_TYPE( macro ) \
macro( A, 0, { std::cout << "A"; } ) \
macro( B, 1, { std::cout << "B"; } ) \
macro( C, 2, { std::cout << "C"; } )
// Now we use that recursive macro to:
// Create an enum and calculate the number of types used
#define ENUM_ITEM( type, id, code ) \
e_##type,
enum AllTypes {
FOREACH_TYPE( ENUM_ITEM )
AllTypes_count
};
#undef ENUM_ITEM
// Now we can create an array of function pointers
typedef void (*function_t)();
function_t func[ AllTypes_count ];
// We can create all classes:
#define CREATE_TYPE( type, the_id, code ) \
struct type {\
static const int id = the_id; \
static void func() code\
};
FOREACH_TYPE( CREATE_TYPE )
#undef CREATE_TYPE
// And create a function that will
#define REGISTER_TYPE( type, id, code ) \
func[ i++ ] = &type::func;
void perform_registration() {
int i = 0;
FOREACH_TYPE( REGISTER_TYPE );
};
#undef REGISTER_TYPE
// And now we can test it
int main() {
perform_registration();
for ( int i = 0; i < AllTypes_count; ++i ) {
func[ i ]();
}
}
This is, on the other hand a maintenance nightmare, quite fragile and hard to debug. Adding new types is trivial, just add a new line to the FOREACH_TYPE macro and you are done... and the best of lucks once something fails...
Templates and metaprogramming
On the other hand, using templates you can get close but you cannot get to the single point of definition for the types. You can automate some of the operations in different ways, but at the very least you will need to define the types themselves and add them to a typelist to get the rest of the functionality.
Simplifying the definition of the actual type_list with C++0x code you can start by defining the types and then creating the type_list. If you want to avoid using C++0x, then take a look at the Loki library, but with C++0x a type list is simple enough:
template <typename ... Args> type_list {}; // generic type list
typedef type_list< A, B, C, D > types; // our concrete list of types A, B, C and D
// this is the only source of duplication:
// types must be defined and added to the
// type_list manually [*]
Now we need to use some metaprogramming to operate on the type list, we can for example count the number of elements in the list:
template <typename List> struct size; // declare
template <typename T, typename ... Args> // general case (recursion)
struct size< type_list<T,Args...> > {
static const int value = 1 + size< type_list<Args...>::value;
};
template <> // stop condition for the recursion
struct size< type_list<> > {
static const int value = 0;
};
Having the size of the type list is a first step in our problem, as it allows us to define an array of functions:
typedef void (*function_t)(); // signature of each function pointer
struct registry {
static const int size = ::size< types >::value;
static const function_t table[ size ];
};
function_t registry::table[ registry::size ]; // define the array of pointers
Now we want to register the static functions from each particular type in that array, and for that we create an auxiliar function (encapsulated as a static function in a type to allow for partial specializations). Note that this concrete part is designed to be run during initialization: it will NOT be compile time, but the cost should be trivial (I would be more worried on the binary size with all the templates):
template <typename T, int N> // declaration
struct register_types_impl;
template <typename T, typename ... Args, int N> // general recursion case
struct register_types_impl< type_list<T,Args...>, N> {
static int apply() {
registry::table[ N ] = &T::f; // register function pointer
return register_types_impl< type_list<Args...>, N+1 >;
}
};
template <int N> // stop condition
struct register_types_impl< type_list<>, int N> {
static int apply() { return N; }
};
// and a nicer interface:
int register_types() {
register_types_impl< types, 0 >();
}
Now we need an id function that maps our types to the function pointer, which in our case is the position of the type in the type list
template <typename T, typename List, int N> // same old, same old... declaration
struct id_impl;
template <typename T, typename U, typename ... Args, int N>
struct id_impl< T, type_list<U, Args...>, N > { // general recursion
static const int value = id_impl< T, type_list<Args...>, N+1 >;
};
template <typename T, typename ... Args, int N> // stop condition 1: type found
struct id_impl< T, type_list<T, Args...>, N> {
static const int value = N;
};
template <typename T, int N> // stop condition 2: type not found
struct id_impl< T, type_list<>, N> {
static const int value = -1;
}
// and a cleaner interface
template <typename T, typename List>
struct id {
static const int value = id_impl<T, List, 0>::value;
};
Now you just need to trigger the registration at runtime, before any other code:
int main() {
register_types(); // this will build the lookup table
}
[*] Well... sort of, you can use a macro trick to reuse the types, as the use of macros is limited, it will not be that hard to maintain/debug.
The compiler knows all f()s of all instantiated classes at compile-time.
There's your mistake. The compiler knows nothing about template instantiations in other compilation units. It should now be pretty obvious why the number of instantiations isn't a constant integral expression that could be used as a template argument (and what if std::array was specialized? Halting Problem ahead!)

How to iterate over a boost::fusion sequence?

I'm trying to initialise a list of args to use with fusion::invoke.
The args are all of the form:
template <typename Type>
struct ArgWrapper
{
inline ArgWrapper(){}
inline void Setup(lua_State*L,int idx)
{
//setup this value from the lua state...
//in reality this class is specialised for different lua types
}
operator Type(){return value;}
Type value;
};
So I can do, for example
int add(int a,int b){return a+b;}
fusion::vector<ArgsWrapper<int>,ArgsWrapper<int> > v;
fusion::at_c<0>(v).value=1;
fusion::at_c<1>(v).value=2;
std::cout<<fusion::invoke(add,v)//prints 3
But if I have a fusion sequence of type FusionListType, where I know each type in the sequence is an ArgWrapper of some type, how can I iterate through that list and call the Setup function on each element (I have just one lua_State pointer and want to use it as the first argument for Setup, and I want to use the position in the sequence as the second argument).
So for a vector of size 3 I want the resultant logic to be:
lua_State*L;
fusion::at_c<0>.Setup(L,1);
fusion::at_c<1>.Setup(L,2);
fusion::at_c<2>.Setup(L,3);
I have tried:
template<typename ArgWrapperType,int N>
void FillArgWrapper(ArgWrapperType arg,lua_State*L)
{
fusion::at_c<N>(arg).Setup(L,N+1);
}
template<typename ArgWrapperType>
void FillArgWrapper<ArgWrapperType,0>(ArgWrapperType arg,lua_State*L)
{
fusion::at_c<0>(arg).Setup(L,1);
}
But this fails to compile, saying function template partial specialisation ‘FillArgWrapper<ArgWrapperType, 0>’ is not allowed.
Thanks in advance.
Ok, I figured it out. I need to be using a struct:
template <typename ArgWrapperList,u32 N=mpl::size<ArgWrapperList>::value-1>
struct ArgWrapperListFiller
{
static inline void Setup(ArgWrapperList &args,lua_State*L)
{
fusion::at_c<N>(args).Setup(L,N+1);
ArgWrapperListFiller<ArgWrapperList,N-1>::Setup(args,L);
}
};
template <typename ArgWrapperList> //base case, do not recurse
struct ArgWrapperListFiller<ArgWrapperList,0>
{
static inline void Fill(ArgWrapperList &args,lua_State*L)
{
fusion::at_c<0>(args).Setup(L,1);
};
};