C++ 强制 mem_fun 选择特定的重载成员函数

Posted

技术标签:

【中文标题】C++ 强制 mem_fun 选择特定的重载成员函数【英文标题】:C++ forcing mem_fun to select a specific overloaded member function 【发布时间】:2012-03-05 15:55:08 【问题描述】:

我实际上已经想出了如何按照我的问题标题所暗示的方式去做,但不是以一种令人满意和便携的方式。让我更具体一点。

这是我的代码的精简和修改版本:

#include <algorithm>
#include <functional>

class A 
public:
    int  my_val() const  return _val; ;
    int& my_val()  throw "Can't do this"; ;
        // My class is actually derived from a super class which has both functions, but I don't want A to be able to access this second version
private:
    int _val;


std::vector<int> get_int_vector(const std::vector<A*>& a) 
    std::vector<int> b;
    b.reserve(a.size());
    transform( a.begin(), a.end(), inserter( b, b.end() ),
        std::mem_fun<int, const A>(&A::my_val) );
    return b;

现在,我的问题是这段代码在带有 Microsoft Visual Studio C++ 2008 的 Windows 7 中编译和运行良好,但在带有 g++(版本 4.1.2 20080704)的 Red Hat linux 中却没有,我收到以下错误:

error: call of overloaded 'mem_fun(<unresolved overloaded function type>)' is ambiguous
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:713: note: candidates are: std::mem_fun_t<_Ret, _Tp> std::mem_fun(_Ret (_Tp::*)()) [with _Ret = int, _Tp = const A]
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:718: note:                 std::const_mem_fun_t<_Ret, _Tp> std::mem_fun(_Ret (_Tp::*)()const) [with _Ret = int, _Tp = const A]

在 linux 中,如果我将 mem_fun() 调用替换为:mem_fun( static_cast&lt;int (A::*)() const&gt;(&amp;A::my_val) ),它可以编译并正常工作。然而,我发现这个解决方案不如第一个解决方案美观。有没有另一种便携的方式来做我想做的事? (也许有一种明显简单的方法可以做到这一点,我只是在大惊小怪......)

提前谢谢你。 -曼努埃尔

【问题讨论】:

【参考方案1】:

我不确定你的情况,但这对我来说会更令人愉悦。定义你自己的函数:

template <typename S,typename T>
inline std::const_mem_fun_t<S,T> const_mem_fun(S (T::*f)() const)

  return std::const_mem_fun_t<S,T>(f);

并像这样使用它:

std::vector<int> get_int_vector(const std::vector<A*>& a) 
    std::vector<int> b;
    b.reserve(a.size());
    transform( a.begin(), a.end(), inserter( b, b.end() ),
        const_mem_fun(&A::my_val) );
    return b;

避免演员表的另一种选择是这样的:

std::vector<int> get_int_vector(const std::vector<A*>& a) 
    std::vector<int> b;
    b.reserve(a.size());
    int& (A::*my_val)() const = &A::my_val;
    transform( a.begin(), a.end(), inserter( b, b.end() ), std::mem_fun(my_val) );
    return b;

【讨论】:

我认为这一点你最好引入 boost bind(或者 std::bind 如果你有它)或者只使用一个循环。 @111111: boost::bind 在这里无济于事,因为真正的问题是,当您将表达式传递给可以解析为多个重载的绑定器时,C++ 没有语法,除了强制转换,以指定要传递的重载。 谢谢 Vaughn,我想这就是我想要的。请注意,您的代码用 g++ 编译,但不能用 MS Visual Studio 编译,它抱怨“错误 C2914: 'const_mem_fun' : cannot deuce template argument as function argument is ambiguous”,所以我必须指定const_mem_fun&lt;int,A&gt;(...) 我添加了另一种选择。它不是特别漂亮,但它确实避免了演员表,而且我认为它是便携的。 是的,您的替代方案是可移植的,事实上我一点也不觉得难看。谢谢!【参考方案2】:
typedef int (A::*MethodType)() const;
const_mem_fun(MethodType(&A::my_val));

这就是想法。

【讨论】:

以上是关于C++ 强制 mem_fun 选择特定的重载成员函数的主要内容,如果未能解决你的问题,请参考以下文章

C++ 操作符重载形式——成员函数 or 友元函数

[ C++ ] 类与对象(下)日期类Date补充及流提取和流插入运算符重载

C++ 成员函数重载与 &(和号)

逆向第十九讲——类继承和成员类运算符重载模板逆向20171211

c++ 拷贝构造函数与赋值运算符重载函数的区别是

c++中拷贝构造函数和赋值运算符重载本质上一样么