I think both calls are invalid because both are related to unallocated context. From ยง14.8.2.5:
Impossible contexts:
- [..]
- a package of function parameters that does not occur at the end of the list of parameter declarations.
If a type name is specified in a way that includes an inferior context, all types that contain that type name are also not inferred.
If you have void (T::*f)(Args..., int) , that is, in an undetectable context, because the package of function parameters inside the function does not occur at the end. The fact that the member-pointer argument list is not displayed makes the entire function call not output. Thus, this call cannot be deduced:
b.helper(&Base::bar);
For the second one, although it looks, although you explicitly specify Args... , the argument void (T::*f)(Args..., int) is still in an undetectable context, so the compiler does not know if more Args is required.
One solution is to make this argument not output using, say, an identity trick back:
template <typename T, typename... Args> void foo (void (T::*)(typename identity<Args>::type..., int), Args...);
Thus, both of these lines are compiled:
b.helper(&Base::bar); d.helper<Derived, double>(&Derived::baz, 3.14);
Although now you need to make sure that you get Args... exactly if you have not explicitly specified it.