在C ++中,我不太明白如何通过定义自定义函数来对元素进行排序。
Cppreference.com说比较功能:
comp - 比较函数,如果是第一个参数,则返回true 小于第二个。
bool cmp(const Type1& a,const Type2& b);
当然我认为对于排序元素我需要定义一个度量,sort函数会根据度量对它们进行排序。
在我的实际例子中,我想根据它们与相机的距离来对图像文件进行排序。我有一个boost :: filesystem :: path的矢量链接到图像序列的目录
vector<boost::filesystem::path> path_vec
我自然会认为我需要写一个像
这样的函数double z_distance( boost::filesystem::path filename, integer time )
什么会为所有元素返回一个double,并按每个帧的升序或降序对它们进行排序(从而改变参数中的时间)。
你能告诉我如何将这个返回单个值的函数转换为sort函数所需的bool函数吗?
如果我只能传递函数名称而不是对函数的完整调用,我怎么能传递参数?
答案 0 :(得分:3)
定义时
bool nearer(const boost::filesystem::path& a, const boost::filesystem::path& b)
{
int somevalue = 0;
return z_distance(a, somevalue) < z_distance(b, somevalue);
}
你可以做到
std::sort(path_vec.begin(), path_vec.end(), nearer);
但是,我不知道如何处理函数z_distance()
的第二个参数。也许你可以从你的文件中获取它,或者你必须使用仿函数而不是函数进行比较。对于仿函数,请参阅@templatetypedef给出的答案。
由于您标记了VC ++ 10,您还可以使用C ++ 0x功能:编写lambda表达式(adhoc函数)来传递参数:
int somevalue = 0;
std::sort(path_vec.begin(), path_vec.end(),
[=](const boost::filesystem::path& a, const boost::filesystem::path& b) -> bool
{
return z_distance(a, somevalue) < z_distance(b, somevalue);
}
);
答案 1 :(得分:2)
有很多方法可以做到这一点。
如果您碰巧知道z_distance
的第二个参数总是会有一些固定值,那么您可以通过编写实际进行比较的辅助函数将函数转换为比较器。例如:
bool CompareByDistance(const boost::filesystem::path& lhs,
const boost::filesystem::path& rhs) {
return z_distance(lhs, kSecondArg) < z_distance(rhs, kSecondArg);
}
如果不知道z_distance
函数的第二个参数应该是什么,或者只能在运行时确定,那么您可能需要使用功能对象。函数对象(有时称为仿函数)是一个模仿常规函数的对象。您可以通过传入一些参数来调用它,但因为它是一个对象,除了参数之外,最终被调用的函数还可以访问本地状态。您可以构建的一个这样的函数对象可能如下所示:
class CompareByDistance {
public:
/* Constructor takes in the time that you want to sort at,
* then stores it for later.
*/
CompareByDistance(int time) : mTime(time) {
}
/* This is the function call operator that is called when you try
* treating a CompareByDistance object as a function. Note how it
* uses the mTime field as a parameter to `z_distance`.
*/
bool operator()(const boost::filesystem::path& lhs,
const boost::filesystem::path& rhs) const {
return z_distance(lhs, mTime) < z_distance(rhs, mTime);
}
private:
const int mTime; // Store mTime for later
};
现在,如果你想在某个时间t对所有内容进行排序,你可以写
sort(elems.begin(), elems.end(), CompareByDistance(t));
有关仿函数的更多信息,以及作为一个无耻的插件,这是我为一年前教过的C ++课程写的 a chapter on functors 。
希望这有帮助!
答案 2 :(得分:2)
重载operator<
以返回&amp; A&lt; &amp; B,sort应该只使用begin(),end()和其他内容。
所以
bool operator<(const SomeType& a, const SomeType& b)
{
return z_distance(a, 0) < z_distance(b, 0);
}
你应该可以这样称呼它。
std::vector<SomeType> vec;
std::sort(vec.begin(), vec.end());
答案 3 :(得分:1)
好的,这就是你困惑的地方......
该函数一次比较两个元素,根据结果重新调整内部容器(树或其他)。所以,在STL函数中需要知道的所有C ++都是基于你的函数而不是元素B的elmement A.
所以,对于你所关心的一切,你的比较功能可以比较它们的距离,人的名字,或者你想要的任何东西。如果一个元素小于另一个元素,则该函数必须返回true,C ++将处理如何对其进行排序。