Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual C++ 12 (VS2013 Preview) variadic template with function parameter workaround

I just filed this bug on Microsoft Connect regarding the inability to compile the following toy snippet of code:

template <typename... P> struct S {
    template <void(*F)(P...)> static void T() { }
};

void A(int, float) { }
int main() { S<int, float>::T<&A>(); }

The error is:

test.cpp(2): error C3520: 'P' : parameter pack must be expanded in this context

Essentially, I cannot unpack a variadic type inside of a function signature when used as a template parameter. This code is (I think) legal; at least, GCC 4.7, Clang 3.0, and ICC 13 all support it.

I've seen this SO question but no workarounds are requested or given, which is what I'm looking for.

While not super critical (obviously I've been getting by without variadic templates for many years now) this pattern is of particular importance to some of the work I'd like to do and some articles I'd like to do on C++11 reflection techniques for serialization, script binding, etc. which is something I'd like to be useful to Visual Studio users (as it is by far the dominant compiler toolset in my industry). I'd like to hope that Microsoft's engineers will be able to fix this by 2013 RTM, but I'm not holding my breath.

A toy (from memory this time) sample of how this is being used is something like (minus the macros that make it slightly easier to use):

Reflect<MyType>("MyType")
.bind("GetMatrix", mat44, &MyType::GetMatrix>()
.bind("Display", void, &MyType::Display>();

Of course this can all be done without variadic templates. It just takes large masses of code and accepting limitations to the maximum arity of bound member functions, of course. And yes, passing the functions as a template parameter is of import, due to the nature of how member function pointers work in Visual Studio (variable size) and a desire to achieve efficiency on par with Impossibly Fast C++ Delegates (in my niche of the C++ community, this level of optimization can sometimes actually matter) which negates the option of using std::function or similar designs.

Is there a work-around for this VS bug? Or any other way to use variadic templates to use a (compile-time) function pointer parameter in VC++12?

like image 261
Sean Middleditch Avatar asked Jul 01 '13 08:07

Sean Middleditch


1 Answers

Not sure why but simplifying with a typedef seems to work:

template <typename... P>
struct S
{
    typedef void (*MyFunc)(P...);

    template <MyFunc myFunc>
    static void foo() {}
};

void foo2(int, float) {}

int main()
{
    S<int, float>::foo<&foo2>();
}

At least on the Visual Studio 2013 Ultimate Preview.

like image 79
Jens Åkerblom Avatar answered Oct 27 '22 00:10

Jens Åkerblom