プロキシとして機能する次のテンプレート クラスがあります。call
ラップされたオブジェクトでメソッドを呼び出すために使用されることになっているという名前のメソッドがあります。問題があります。型推定が失敗し、その理由がわかりません。
Hudsucker::f
を取り、それへの参照std::string
を渡すかどうかに関係なく、コンパイラは正しいメソッドを呼び出すことができます。std::string
const
しかし、GCC と Clang の両方で型推論へHudsucker::g
のconst
参照が失敗する場合。std::string
最初の行の GCC エラー:
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>’)
特にこのビットは奇妙です: no matching function for call to Proxy<Hudsucker>::call(void (Hudsucker::*)(const string&), const string&)
. それはまさに私が期待する署名です。
最初の行の Clang エラー:
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)
コード:
#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;
}
型推論がそのように失敗する理由を説明できますか? これを参照でコンパイルする方法はありconst
ますか?