【问题标题】:how to generate a compare function from a pointer to member function?如何从指向成员函数的指针生成比较函数?
【发布时间】:2020-08-21 16:31:55
【问题描述】:

为 STL 算法和容器编写比较函数很乏味。

对于像这样的简单对象,

struct Person
{
    int id;
    string name;
    string surname;
    string get_full_name(); // name then surname
};

我必须为lhs 和rhs 键入相同的函数调用:

vector<Person> v = { ... };
std::sort( v.begin(), v.end(), [](const Object &lhs, const Object &rhs) {
    return lhs.get_full_name() < rhs.get_full_name();   // tedious
} );

我希望能够使用指向成员函数或指向成员数据的指针来编写比较函数/仿函数。可能是这样的:

std::sort( v.begin(), v.end(), make_compare_functor( &Object::get_full_name ));
std::sort( v.begin(), v.end(), make_compare_functor( &Object::surname ));

我试过这样实现它:

template <class R, class T>
struct CompareFunctor {
    R (T::*fp)();
    bool operator() (const T& lhs, const T& rhs) { 
           return lhs->*fp() < rhs->*fp();
    }
};

// helper function
template <class R, class T>
CompareFunctor<R,T> make_compare_functor(R(T::*fp)()) {
    return CompareFunctor<R,T> { fp };
}

但它无法为这些情况中的任何实例化T

auto functor1 = make_compare_functor( &Person::get_full_name );
auto functor2 = make_compare_functor( &std::string::size );

(错误信息如:'make_compare_functor': no matching overloaded function found ... note: could be 'const Person' or 'Person')

谁能指导我如何使用指向成员函数的指针来编写比较函数/仿函数?

最好是基于 STL 的 -- 没有 Boost 或其他库。

【问题讨论】:

  • 没有 Boost 或其他库。 -- 好吧,如果 Boost 中有什么东西可以解决您的问题,您是否不需要简单地查看 Boost 源代码和看看他们做了什么来回答你的问题?

标签: c++ c++11 stl


【解决方案1】:

您在正确的轨道上,但您需要重载 make_compare_functor 以同时接受指向成员函数的指针以及指向成员的指针。此外,您需要编写一个 CompareMember 来比较指针到成员,类似于 CompareFunctor 比较指针到成员函数的方式:

// compare pointer to member function
template <class R, class T>
struct CompareFunctor {
    R (T::*fp)() const;
    bool operator() (const T& lhs, const T& rhs) { 
           return (lhs.*fp)() < (rhs.*fp)();
    }
};

// compare pointer to member
template <class T, class M>
struct CompareMember {
    M T::*mp;
    bool operator() (const T& lhs, const T& rhs) { 
           return lhs.*mp < rhs.*mp;
    }
};

// helper function : compare pointer to member function
template <class R, class T>
CompareFunctor<R,T> make_compare_functor(R(T::*fp)() const) {
    return CompareFunctor<R,T> { fp };
}

// helper function : compare pointer to member 
template <class T, class M>
CompareMember<T, M> make_compare_functor(M T::*mp) {
    return CompareMember<T, M> { mp };
}

这是demo。

请注意,我将const 添加到指向成员函数的签名中,并更正了问题代码中的几个拼写错误。

另外,make_compare_functor 也应该重命名为 make_compare,因为它也接受指向成员的指针。

【讨论】:

  • 感谢您的反馈,但我什至无法实例化 CompareFunctor !尝试调用:auto f = make_compare_functor( &amp;Person::get_full_name ); 无法编译!
  • 您是否点击了演示链接?它为我编译。
  • 啊哈!显然您的版本可以编译,因为您将函数指针声明为 const : ` R (T::*fp)() const;. Does that mean that this pointer can only be assigned to and call const` functions ?
  • 不,您也可以将它与非常量函数一起使用,但您不应该这样做,因为将非常量函数作为比较器传递实际上没有意义。
猜你喜欢
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多