我想创建一个std::set
具有自定义比较功能的。我可以将它定义为一个带有 的类operator()
,但我想享受定义一个使用它的 lambda 的能力,所以我决定在具有 的类的构造函数的初始化列表中定义 lambda 函数std::set
作为成员。但我无法获得 lambda 的类型。在我继续之前,这里有一个例子:
class Foo
{
private:
std::set<int, /*???*/> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
经过搜索,我找到了两种解决方案:一种,使用std::function
. 只需设置比较函数类型std::function<bool (int, int)>
并像我一样传递 lambda。第二种解决方案是编写一个 make_set 函数,例如std::make_pair
.
解决方案 1:
class Foo
{
private:
std::set<int, std::function<bool (int, int)> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
解决方案 2:
template <class Key, class Compare>
std::set<Key, Compare> make_set (Compare compare)
{
return std::set<Key, Compare> (compare);
}
问题是,我有充分的理由更喜欢一种解决方案吗?我更喜欢第一个,因为它使用了标准功能(make_set 不是标准功能),但我想知道:使用是否std::function
会使代码(可能)变慢?我的意思是,它是否会降低编译器内联比较函数的机会,或者它应该足够聪明以表现得与它是 lambda 函数类型一样,而不是std::function
(我知道,在这种情况下它不能是lambda 类型,但你知道,我问的是一般情况)?
(我使用 GCC,但我想知道流行的编译器一般会做什么)
总结,在我得到很多很好的答案之后:
如果速度很关键,最好的解决方案是使用带有operator()
aka functor 的类。编译器最容易优化和避免任何间接。
为了便于维护和更好的通用解决方案,使用 C++11 特性,使用std::function
. 它仍然很快(只是比仿函数慢一点,但可以忽略不计),您可以使用任何函数 - std::function
、 lambda 、任何可调用对象。
还有一个使用函数指针的选项,但如果没有速度问题我认为std::function
更好(如果你使用 C++11)。
有一个选项可以在其他地方定义 lambda 函数,但是您不会从比较函数作为 lambda 表达式中获得任何收益,因为您也可以将其设为一个类,operator()
并且定义的位置无论如何都不会是集合构造。
还有更多的想法,比如使用委托。如果您想更全面地解释所有解决方案,请阅读答案:)