Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC: Function wrapper template troubles

I am on GCC 5.3 trying to get some function wrapper code to work which works fine on clang. Here is a boiled down example:

#include <iostream>
using namespace std;

template<class Sig, Sig F>
struct FunctionWrapper;


template<class Ret, class... Args, Ret (*Func)(Args...)>
struct FunctionWrapper<Ret(Args...), Func>
{
};

static int testFunc(int _a, int _b)
{
    return _a + _b;
}


int main() {
    FunctionWrapper<int(int, int), testFunc> wrapper;
    return 0;
}

The error I get on gcc is the following:

prog.cpp:9:46: error: 'Ret(Args ...)' is not a valid type for a template non-type parameter struct FunctionWrapper ^ prog.cpp: In function 'int main()': prog.cpp:20:45: error: 'int(int, int)' is not a valid type for a template non-type parameter FunctionWrapper wrapper;

Any ideas about how to make this work on both, clang and gcc?

Thanks!

like image 836
moka Avatar asked Jun 06 '16 20:06

moka


1 Answers

I think this is a gcc bug. According to [temp.param]:

A non-type template-parameter of type “array of T” or of function type T is adjusted to be of type “pointer to T”.

Having Ret(Args...) as a template non-type parameter is equivalent to having Ret(*)(Args...) as a template non-type parameter.

Note that gcc does [correctly] compile the following example, which is basically the same idea as your original version:

static int testFunc(int _a, int _b)
{
    return _a + _b;
}

template <int F(int, int)>
struct Foo { };


int main() {
    Foo<testFunc> wrapper;
    return 0;
}

As a workaround, simply forcing the non-type argument to be a pointer is allowed by both compilers:

template<class Sig, Sig* F>
struct FunctionWrapper;


template<class Ret, class... Args, Ret (*Func)(Args...)>
struct FunctionWrapper<Ret(Args...), Func>
{ };

but I don't believe that this should have been necessary.

like image 82
Barry Avatar answered Oct 19 '22 05:10

Barry