#include <iostream>
using namespace std;
template<class This, class Ret, class... Args>
void CallMe(This* aThis, Ret(This::*aMethod)(Args...), Args... aArgs)
{
// Should not use std::forward without universal reference.
(aThis->*aMethod)(std::forward<Args>(aArgs)...);
}
template<class This, class Ret, class... Args, class... ActualArgs>
void CallMe2(This* aThis, Ret(This::*aMethod)(Args...), ActualArgs&&... aArgs)
{
(aThis->*aMethod)(std::forward<ActualArgs>(aArgs)...);
}
class Foo
{
public:
Foo() {}
Foo(const Foo&) { cout << "copy" << endl; }
Foo(Foo&&) { cout << "move" << endl; }
};
class Bar
{
public:
void Call(Foo& aFoo) { cout << "Invoke" << endl; }
};
int main() {
Bar b;
Foo f;
//Will lead to a deduction ambiguity.
CallMe(&b, &Bar::Call, f);
//This version can fix the problem.
//CallMe2(&b, &Bar::Call, f);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGU8Y2xhc3MgVGhpcywgY2xhc3MgUmV0LCBjbGFzcy4uLiBBcmdzPgp2b2lkIENhbGxNZShUaGlzKiBhVGhpcywgUmV0KFRoaXM6OiphTWV0aG9kKShBcmdzLi4uKSwgQXJncy4uLiBhQXJncykKewoJLy8gU2hvdWxkIG5vdCB1c2Ugc3RkOjpmb3J3YXJkIHdpdGhvdXQgdW5pdmVyc2FsIHJlZmVyZW5jZS4KCShhVGhpcy0+KmFNZXRob2QpKHN0ZDo6Zm9yd2FyZDxBcmdzPihhQXJncykuLi4pOwp9CgoKdGVtcGxhdGU8Y2xhc3MgVGhpcywgY2xhc3MgUmV0LCBjbGFzcy4uLiBBcmdzLCBjbGFzcy4uLiBBY3R1YWxBcmdzPgp2b2lkIENhbGxNZTIoVGhpcyogYVRoaXMsIFJldChUaGlzOjoqYU1ldGhvZCkoQXJncy4uLiksIEFjdHVhbEFyZ3MmJi4uLiBhQXJncykKewoJKGFUaGlzLT4qYU1ldGhvZCkoc3RkOjpmb3J3YXJkPEFjdHVhbEFyZ3M+KGFBcmdzKS4uLik7Cn0KCmNsYXNzIEZvbwp7CnB1YmxpYzoKCUZvbygpIHt9CglGb28oY29uc3QgRm9vJikgeyBjb3V0IDw8ICJjb3B5IiA8PCBlbmRsOyB9CglGb28oRm9vJiYpIHsgY291dCA8PCAibW92ZSIgPDwgZW5kbDsgfQp9OwoKY2xhc3MgQmFyCnsKcHVibGljOgoJdm9pZCBDYWxsKEZvbyYgYUZvbykgeyBjb3V0IDw8ICJJbnZva2UiIDw8IGVuZGw7IH0KfTsKaW50IG1haW4oKSB7CglCYXIgYjsKCUZvbyBmOwoJLy9XaWxsIGxlYWQgdG8gYSBkZWR1Y3Rpb24gYW1iaWd1aXR5LgoJQ2FsbE1lKCZiLCAmQmFyOjpDYWxsLCBmKTsKCS8vVGhpcyB2ZXJzaW9uIGNhbiBmaXggdGhlIHByb2JsZW0uCgkvL0NhbGxNZTIoJmIsICZCYXI6OkNhbGwsIGYpOwoJcmV0dXJuIDA7Cn0=
prog.cpp: In function 'int main()':
prog.cpp:35:26: error: no matching function for call to 'CallMe(Bar*, void (Bar::*)(Foo&), Foo&)'
CallMe(&b, &Bar::Call, f);
^
prog.cpp:5:6: note: candidate: template<class This, class Ret, class ... Args> void CallMe(This*, Ret (This::*)(Args ...), Args ...)
void CallMe(This* aThis, Ret(This::*aMethod)(Args...), Args... aArgs)
^
prog.cpp:5:6: note: template argument deduction/substitution failed:
prog.cpp:35:26: note: inconsistent parameter pack deduction with 'Foo&' and 'Foo'
CallMe(&b, &Bar::Call, f);
^