如何在C++类中结合algorithm头使用成员比较函数?
问题场景
你在类中定义了非静态成员函数smallest_weight用于比较:
bool smallest_weight(const size_t& i, const size_t& j) { return this->abs_weight[i] < this->abs_weight[j]; }
并在构造函数中调用std::min_element时传入该函数作为比较器:
size_t best_node = *min_element( this->pointer_list[i + 1].begin(), this->pointer_list[i + 1].end(), smallest_weight );
编译时触发错误:
error: invalid use of non-static member function ‘bool TimeCalculator::smallest_weight(const size_t&, const size_t&)’
由于该函数需要访问类内成员abs_weight,无法设为static,同时不想将数组全局化,可通过以下几种方式解决:
解决方案
1. 使用Lambda表达式(C++11及以上,推荐)
Lambda可以直接捕获当前对象的this指针,无需单独定义成员函数,代码更紧凑直观:
size_t best_node = *min_element( this->pointer_list[i + 1].begin(), this->pointer_list[i + 1].end(), [this](const size_t& a, const size_t& b) { return this->abs_weight[a] < this->abs_weight[b]; } );
这里Lambda捕获this后,就能直接访问类内的abs_weight成员,完全替代原来的smallest_weight函数。
2. 使用std::bind绑定当前对象
如果想保留原有的smallest_weight成员函数,可以用std::bind将成员函数与当前对象绑定,生成符合std::min_element要求的可调用对象。需要先包含<functional>头文件:
#include <functional> // ... size_t best_node = *min_element( this->pointer_list[i + 1].begin(), this->pointer_list[i + 1].end(), std::bind(&TimeCalculator::smallest_weight, this, std::placeholders::_1, std::placeholders::_2) );
std::bind将成员函数的隐含第一个参数(this指针)绑定到当前对象,std::placeholders::_1和_2分别对应比较器需要的两个输入参数。
3. 定义仿函数(适用于C++11之前的版本)
若项目使用旧版C++标准,可在类内定义嵌套的仿函数类,通过持有类对象的引用来访问成员变量:
class TimeCalculator { private: std::vector<double> abs_weight; std::vector<std::vector<size_t>> pointer_list; // 嵌套仿函数类 struct SmallestWeightComparator { TimeCalculator& parent; explicit SmallestWeightComparator(TimeCalculator& p) : parent(p) {} bool operator()(const size_t& a, const size_t& b) { return parent.abs_weight[a] < parent.abs_weight[b]; } }; public: TimeCalculator() { size_t i = 0; // 示例中的合法索引值 size_t best_node = *min_element( this->pointer_list[i + 1].begin(), this->pointer_list[i + 1].end(), SmallestWeightComparator(*this) ); } };
仿函数通过构造函数接收当前类对象的引用,在重载的operator()中实现比较逻辑,满足std::min_element对比较器的要求。
内容的提问来源于stack exchange,提问作者R1D3R175

