这个问题源于
将指向重载类方法的成员函数指针传递到模板函数中 https://stackoverflow.com/questions/31309846/passing-a-member-function-pointer-to-an-overloaded-class-method-into-a-template.
您无需阅读该内容即可理解这个问题。也许这两个问题都会有相同的答案。
我正进入(状态以下简单代码的编译器错误 http://ideone.com/wJvaxn.
#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'
如果你看一下notes 很接近,那么编译器似乎正在匹配除正确方法之外的所有其他方法!在这种情况下,编译器应该匹配insert(const std::set<int>::value_type&)
aka const int&
。如果我改变ReceiveFuncPtr()
为了匹配其他一些重载,它会再次因跳过该重载而失败。
为了调试这种情况,我创建了手工版本std::set
。但那个编译良好 http://ideone.com/ioNWD3:
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
}
上网冲浪后,我看到了这个帖子:
标准函数的函数指针和成员函数指针的规则是什么? https://stackoverflow.com/questions/13521030/what-are-the-rules-for-function-pointers-and-member-function-pointers-to-standar
虽然有关系,但并不能解决问题。
Question:为什么在标准库方法中成员函数替换会失败,而在手写类方法中却同样如此?
Update:
看完正确答案后,我确信insert
不能使用。唯一的方法是丑陋的类型转换,这对于这个问题来说是一种矫枉过正的做法。
一优雅solution是使用std::set<int>::emplace<const int&>
其中只有template
d 版本不同于插入,它混合了template
和非template
版本。
调用该函数如下:
ReceiveFuncPtr(&std::set<int>::emplace<const int&>);
Above 编译良好 http://ideone.com/ps4PJb.