![](/img/trans.png)
[英]C++ When should we prefer to use a two chained static_cast over reinterpret_cast
[英]Why should I prefer a separate function over a static method for functional programming in c++?
在我的另一个问题中, 如何使用 static 方法作为 c++ 中的回调,人们解决了我的实际问题,然后建议我采取不同的方法来遵循最佳实践。 我想更好地理解为什么。
这个例子使用了一个比较器,但我真的很想了解函数式编程是否有一般规则(例如,也许还有与 class 等相关的聚合器函数)
比较器 function 的示例用例:
#include <set>
int main() {
std::set<MyClass, decltype(SOMETHING_HERE)> s(SOMETHING_HERE);
return 0;
}
以下是我知道的解决方案,从最推荐到最不推荐(我相信) - 与我目前选择的顺序相反。
使用仿函数的推荐方式(我相信):
struct MyComparator {
bool operator() (MyClass a, MyClass b) const {
return a > b; // Reversed
}
};
std::set<MyClass, MyComparator)> s;
我不喜欢:冗长; 在词汇上与 MyClass 无关; 我不明白为什么 s 没有构造函数参数。 我对缺少参数感到困惑,因为set
似乎在编译时/与类型系统(如本例中)以及在运行时/与指针混合/组合决定比较算法。 如果这只是一种或另一种方式,我会接受“就是这样”。
一种对我来说似乎更好的方法:
auto const my_comparator = [](int a, int b) {
return a > b;
};
std::set<int, decltype(my_comparator)> s(my_comparator);
它更简洁。 意图很明确:它是 function,而不是可能添加到的 class。 传递 object,而不仅仅是类型,对我来说是有意义的(不可能有 2 种不同的实现)。
对我来说最有意义的方法(基于其他语言):
class MyClass {
public:
// More code here
static auto compare_reverse(MyClass a, MyClass b) {
return a > b;
}
};
std::set<int, decltype(&MyClass::compare_reverse)> s(&MyClass::compare_reverse);
它显然与 MyClass 相关(并且在词法上与之相关)。 似乎有效(尽管有人告诉我不是)而且简洁。
任何解释为什么推荐的顺序更好,性能,错误/可维护性,哲学,非常感谢。
首先,请注意,如果您只想要一个>
比较器,则有std::greater<>
和std::greater<MyClass>
( 前者通常是优越的)。
查看您列出的选项:
(1)
struct MyComparator
{
bool operator()(MyClass a, MyClass b) const
{
return a > b;
}
};
std::set<MyClass, MyComparator)> s;
正如你所说,这是推荐的方式。
与 MyClass 没有词法关联
正如评论中所建议的,您可以将它放在MyClass
中。
不明白为什么 s 没有构造函数参数
如果您不将比较器传递给构造函数,则比较器是默认构造的(如果它是默认构造的,否则会出现编译错误)。
您可以手动传递MyComparator{}
,但没有意义。
(2)
auto my_comparator = [](int a, int b)
{
return a > b;
};
std::set<int, decltype(my_comparator)> s(my_comparator);
它完全等同于 (1),除了您被迫将my_comparator
传递给构造函数。 C++20 通过使 lambdas 默认可构造(如果它们没有捕获)来解决此问题,从而使参数变得不必要。
(3)
class MyClass
{
public:
static auto compare_reverse(MyClass a, MyClass b)
{
return a > b;
}
};
std::set<int, decltype(&MyClass::compare_reverse)> s(&MyClass::compare_reverse);
这为您提供了一个额外的功能:您可以在运行时通过将不同的函数传递给构造函数来选择比较器。
这种能力带来了开销:该集合存储了一个指向 function 的指针(通常为 4 或 8 个字节),并且在进行比较时必须查看该指针。
(3.5)
您可以将 function 包装在std::integral_constant
中。 结果等价于(1)。
bool foo(int x, int y) {return x > y;}
std::set<int, std::integral_constant<decltype(&foo), foo>> s;
// Or:
using MyComparator = std::integral_constant<decltype(&foo), foo>;
std::set<int, MyComparator> s;
如果您正在处理现有类型,这很好,它将比较器提供为 function,并且您不想要 (3) 的开销。
所有这些(除了(3))都是等价的。
如果std::greater<>
适用,则应使用它。
否则,我会推荐 (1) 作为最不容易混淆的选项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.