1

I am trying to call function using pointer to member function pointer and parameter packs. Given Below is code:

class DemoClass { public: void Printer(const DemoClass& sc, const int& i) { } }; template<typename R, typename T, typename ... Args/*, typename ... Params*/> void MakeMemberActionDemoClass(R(T::*memberFunction)(Args...), Args&& ... args) { } int main() { DemoClass d; int z; MakeMemberActionDemoClass(&DemoClass::Printer, d, z); } 

I get following error:

error C2782: 'void MakeMemberActionDemoClass(R (__thiscall T::* )(Args...),Args &&...)' : template parameter 'Args' is ambiguous 1> could be 'const DemoClass&, const int&' 1> or 'DemoClass&, int&' 

If I remove && in last parameter of MakeMemberActionDemoClass, only difference in error is following:

1> could be 'const DemoClass&, const int&' 1> or 'DemoClass, int' 

What should I do so that parameter types will be deduced correctly?

Thanks in advance,

1
  • 1
    Use R(T::*memberFunction)(Args...), Params&& ... args, so that they are deduced separately Commented Mar 7, 2016 at 19:59

1 Answer 1

2

Both instances of Args are in a deducible context. They must produce the same type, or your compiler complains it is ambiguous.

One way is to block deduction in one or the other context. The other way is to stop connecting them.

template<class T>struct tag_t{using type=T;}; template<class Tag>using type_t=typename Tag::type; template<class T>using block_deduction=type_t<tag_t<T>>; template<class R, class T, class...Args> void MakeMemberActionDemoClass( R(T::*memberFunction)(Args...), block_deduction<Args>... args ) { } 

this has the cost of possibly copying values twice.

template<class R, class T, class...Args, class...Params> auto MakeMemberActionDemoClass( R(T::*memberFunction)(Args...), Params&&... params ) ->decltype( (std::declval<T*>()->*memberFunction)( std::declval<Params>()... ) ) { } 

will deduce them correctly and let you perfect forward into memberFunction and SFINAE early enough to detect overload failures.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. Please note I cannot make the second solution work - one with decltype. Visual Studio 2013 (update 5) kept on giving me some error. Also, just to note, in first solution if you want to make tuple you will need to use std::forward_as_tuple.
@user1578026 I fixed a typo in the 2nd one. Might help. But VS2013 and 2015 has poor support for decltype, so...
@Piotr damn you operator->* my old foe