Type of link output const in template functions

Below I have a template function called ProxyCall that takes an object, a member function and its arguments. It simply redirects the member function call.

I would like to be able to call a function without using qualifier templates (imagine tons of such calls with multiple arguments). Type inference basically works, but the compilers (both msvc and gcc 4.9) are barf when I try to pass const reference parameters, as in the example.

#include <string> struct Widget { void f(const std::string& s, bool b) {} }; template<typename T, typename... Args> void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) { (obj.*method)(std::forward<Args>(args)...); } int main(int argc, char* argv[]) { Widget w; std::string s; ProxyCall<Widget, const std::string&, bool>(w, &Widget::f, s, true); // OK ProxyCall(w, &Widget::f, (const std::string&)s, true); // also OK ProxyCall(w, &Widget::f, s, true); // ERROR: template parameter is ambiguous return 0; } 

My question is: how can I change the above code so that the compiler automatically infers types without resorting to explicit template selections or explicit casting. This seems to be possible, given that the compiler already knows that the exact argument types are from the Widget :: f signature.

+5
source share
1 answer
 template<typename T, typename... Args> void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) { (obj.*method)(std::forward<Args>(args)...); } 

Args is inferred from both the second argument and the return arguments to ProxyCall .
In your third case, since s not const , Args is displayed on [std::string&, bool] (remember the linking rules for collapsing and forwarding links). However, the signature of member functions is clearly different. Thus, for the first type, two different types are displayed in Args , which leads to a deduction failure.

Instead, make both the parameter types and the arguments independent - and move the object's argument, for the sake of ref-qualifiers:

 template<typename T, typename F, typename... Args> void ProxyCall(T&& obj, F method, Args&&... args) { (std::forward<T>(obj).*method)(std::forward<Args>(args)...); } 
+3
source

Source: https://habr.com/ru/post/1213725/


All Articles