标准库方法的成员函数指针问题 [英] Member function pointer issue with standard library methods

查看:140
本文介绍了标准库方法的成员函数指针问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题来自于

将重载类方法的成员函数指针传递到模板函数中

您无需阅读它即可了解此问题。可能两个问题的答案都相同。

This question is spawned from
Passing a member function pointer to an overloaded class method into a template function.
You need not read that to understand this question. Probably both the questions will have the same answer.

我正在

I am getting 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'

如果您仔细观察 note ,那么似乎编译器正在与除正确方法之外的所有其他方法匹配!在这种情况下,编译器应匹配 insert(const std :: set< int> :: value_type&) aka const int& 。如果更改 ReceiveFuncPtr()以匹配其他一些重载,则跳过该重载将再次失败。

If you look at the notes closely then it appears that compiler is matching all the other methods except the right one! In this case compiler should have matched insert(const std::set<int>::value_type&) aka const int&. If I change the ReceiveFuncPtr() to match some other overload, it will again fail by skipping that overload.

为了调试这种情况,我创建了手工版本的 std :: set 。但是可以很好地编译

To debug this situation, I created handcrafted version of std::set. But that 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
}

冲浪后,我遇到了这个帖子:

什么是

After surfing, I came across this post:
What are the rules for function pointers and member function pointers to Standard functions?

尽管它们是相关的,但不能解决问题。

Though it's related , it doesn't solve problem.

问题:为什么在手写库方法传递相同内容的情况下,在标准库方法下成员函数替换失败?

Question: Why member function substitution fails in case of standard library method when the the same thing passes for handwritten class method?

更新

查看正确答案后,我确定插入不能使用。唯一的方法是丑陋的类型转换,这对于此问题是一个过大的杀伤力。

一个优雅的解决方案是使用 std :: set< int> ::: emplace< const int&> 仅具有 template d版本,与insert混合具有 template 和非模板版本。

调用以下函数:

After looking at the correct answer, I am sure that insert cannot be used. The only way would be ugly typecasting which is an overkill for this problem.
One elegant solution is to use std::set<int>::emplace<const int&> which has only templated version unlike insert which has mix of template and non-template versions.
Call the function as below:

ReceiveFuncPtr(&std::set<int>::emplace<const int&>);

编译正常

推荐答案

问题不是插入 MySet 中显示的code>函数。问题出在您遗漏的问题之一。具体来说:

The problem isn't with the insert functions you showed in MySet. The problem is with one of the ones you omitted. Specifically:

template< class InputIt >
void insert( InputIt first, InputIt last );

来自[temp.deduct.call]:

From [temp.deduct.call]:


当P是函数类型,指向函数类型的指针或指向成员函数类型的指针时:

—如果参数是包含一个或多个函数模板的重载集,则将参数
视为非推论上下文。

When P is a function type, pointer to function type, or pointer to member function type:
— If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.

由于 & std :: set< int> :: insert 恰好是这样的重载集,参数是非推导上下文,无法解析。您的 MySet 示例不包含 insert 的函数模板重载,这就是为什么它可以正常工作的原因。如果您添加一个,则会看到它也将无法编译。

Since &std::set<int>::insert is precisely such an overload set, the parameter is a non-deduced context and cannot be resolved. Your example of MySet does not contain a function template overload for insert, which is why it works fine. If you add one, you'll see that it will also fail to compile.

这篇关于标准库方法的成员函数指针问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆