【发布时间】:2015-09-27 18:06:16
【问题描述】:
这个问题来自
Passing a member function pointer to an overloaded class method into a template function。
您无需阅读即可理解这个问题。可能这两个问题都会有相同的答案。
我收到compiler error for below simple code。
#include<set>
template<typename Return, typename T>
T ReceiveFuncPtr (Return (T::*Method)(const int&))
{
T obj; // Found and declared an object of actual container class
(obj.*Method)(1); // Some processing
return obj; // Returned that container class object with RVO
}
int main ()
{
ReceiveFuncPtr(&std::set<int>::insert); // ERROR
}
这个错误很有趣:
In function 'int main()':
error: no matching function for call to 'ReceiveFuncPtr(<unresolved overloaded function type>)'
ReceiveFuncPtr(&std::set<int>::insert); // ERROR
^
note: candidate is:
note: template<class Return, class T> T ReceiveFuncPtr(Return (T::*)(const int&))
T ReceiveFuncPtr (Return (T::*Method)(const int&))
^
note: template argument deduction/substitution failed:
note: mismatched types 'const int&' and 'std::initializer_list<int>'
ReceiveFuncPtr(&std::set<int>::insert); // ERROR
^
note: mismatched types 'const int&' and 'std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}'
note: mismatched types 'const int&' and 'std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}'
note: mismatched types 'const int&' and 'std::set<int>::value_type&& {aka int&&}'
note: couldn't deduce template parameter 'Return'
如果您仔细查看注释,那么编译器似乎正在匹配除正确方法之外的所有其他方法!在这种情况下,编译器应该匹配 insert(const std::set<int>::value_type&) aka const int&。如果我更改 ReceiveFuncPtr() 以匹配其他重载,它将再次通过跳过该重载而失败。
为了调试这种情况,我创建了 std::set 的手工版本。但是那个compiles fine:
template<typename T, typename T2 = void>
struct MySet
{
std::pair<T,bool> insert (const T& i) { return std::pair<T,bool>(T(),true); }
std::pair<T,bool> insert (T&& i) { return std::pair<T,bool>(T(),true); }
void insert (std::initializer_list<T> i) { return false; }
}
int main ()
{
ReceiveFuncPtr(&MySet<int>::insert); // OK
}
上网后偶然发现这个帖子:
What are the rules for function pointers and member function pointers to Standard functions?
虽然有关系,但解决不了问题。
问题:为什么在标准库方法的情况下,当手写类方法通过相同的事情时,成员函数替换失败?
更新:
看了正确答案后,我确定insert是不能用的。唯一的方法是丑陋的类型转换,这对于这个问题来说太过分了。
一种优雅的解决方案是使用std::set<int>::emplace<const int&>,它只有templated 版本,而insert 则混合了template 和非template 版本。
调用函数如下:
ReceiveFuncPtr(&std::set<int>::emplace<const int&>);
【问题讨论】:
-
它实际上可以在带有 Visual Studio 2013 的 MSVC 上编译并运行良好:
template <class T, class Ret> T exec(Ret(T::*func)(const int& i)){ T t; (t.*func)(4); return t; }
标签: c++ templates c++11 standard-library member-function-pointers