I have the following template class which acts as a proxy. It has a method named call
which is supposed to be used to call methods on the wrapped object. There's a problem with it. The type deduction fails and I cannot understand why.
Hudsucker::f
takes an std::string
and then no matter if I pass an std::string
or a const
reference to it the compiler is able to call the right method.
But in case of Hudsucker::g
with takes a const
reference to std::string
type deduction fails in both cases with both GCC and Clang.
GCC error for the first line:
main.cpp:36:28: error: no matching function for call to ‘Proxy<Hudsucker>::call(void (Hudsucker::*)(const string&), const string&)’
main.cpp:36:28: note: candidate is:
main.cpp:10:10: note: template<class A> void Proxy::call(void (T::*)(A), A) [with A = A; T = Hudsucker]
main.cpp:10:10: note: template argument deduction/substitution failed:
main.cpp:36:28: note: deduced conflicting types for parameter ‘A’ (‘const std::basic_string<char>&’ and ‘std::basic_string<char>’)
Especially this bit is strange: no matching function for call to Proxy<Hudsucker>::call(void (Hudsucker::*)(const string&), const string&)
. That is exactly the signature I would expect to see work.
Clang error for the first line:
main.cpp:36:7: error: no matching member function for call to 'call'
p.call(&Hudsucker::g, s); // <- Compile error
~~^~~~
main.cpp:10:10: note: candidate template ignored: deduced conflicting types for parameter 'A' ('const std::basic_string<char> &' vs. 'std::basic_string<char>')
void call(void (T::*f)(A), A a)
Code:
#include <string>
#include <iostream>
template <typename T> class Proxy
{
public:
Proxy(T &o): o_(o) {}
template <typename A>
void call(void (T::*f)(A), A a)
{
(o_.*f)(a);
}
private:
T &o_;
};
class Hudsucker
{
public:
void f(std::string s) {}
void g(std::string const &s) {}
};
int main()
{
Hudsucker h;
Proxy<Hudsucker> p(h);
std::string const s = "For kids, you know.";
std::string const &r = s;
p.call(&Hudsucker::f, s);
p.call(&Hudsucker::f, r);
p.call(&Hudsucker::g, s); // <- Compile error
p.call(&Hudsucker::g, r); // <- Compile error
return 0;
}
Could you explain why the type deduction fails in that way? Is there a way to get this to compile with const
references?