Question

// This compiles and runs properly
using MemPtr = Entity&(OBFactory::*)(const Vec2i&, float);
void test(MemPtr mptr, const Vec2i& p, float d)
{
    (getFactory().*mptr)(p, d);
}

//  "no matching function for call to `test`, 
//  failed candidate template argument deduction"
template<typename... A> using MemPtr = Entity&(OBFactory::*)(A...);
template<typename... A> void test(MemPtr<A...> mptr, const Vec2i& p, float d)
{
    (getFactory().*mptr)(p, d);
}

...

// I call both versions with
test(&OBFactory::func, Vec2i{0, 0}, 0.f);

Why doesn't the variadic template version work? Am I missing some forwarding?

Was it helpful?

Solution

I think this could serve as an example of what is happening in your code:

struct A
{
    // there are multiple overloads for func (or a template?)
    void func(double) {}
    void func(int) {}
};

//using MemPtr = void(A::*)(double);
//void test(MemPtr mptr, double d)
//{
//    (A().*mptr)(d);
//}

template<typename... As> using MemPtr = void(A::*)(As...);
template<typename... As> void test(MemPtr<As...> mptr, double d)
{
    (A().*mptr)(d);
}

int main()
{
    // test(&A::func, 0.); // line X
    test(static_cast<void(A::*)(double)>(&A::func), 0.); // line Y
}

The problem in line X is that you use &A::func and the compiler now needs to deduce the As... - which it can't. Line Y fixes that by explicitly casting it to the correct overload.

If you use the first version of test (the one commented out above), test's signature contains the necessary type already (no deduction needed) and the compiler knows how to cast (in this case this means select) the correct overload for func.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top