简体   繁体   English

通用等效于 std function 对象

[英]Generic equivalent to std function objects

Is there any function objects in the boost that are generic equivalents to the std::equal_to, std::greater etc. family of function objects? boost 中是否有任何 function 对象是 std::equal_to、std::greater 等 function 对象系列的通用等价物?

Essentially, std::equal_to should become something like本质上, std::equal_to 应该变成类似

struct generic_equal_to
{
    template <class T, class U>
    bool operator()(const T& t, const U& u) const
    {
        return t == u;
    }
};

I can see how the generic versions of std::plus etc. might be trickier due to issues with the return type (though the decltype can solve that).我可以看到 std::plus 等的通用版本由于返回类型的问题而变得更加棘手(尽管decltype可以解决这个问题)。 I can't see any possible reason why the std::equal_to function object itself should require a template argument, though.不过,我看不出 std::equal_to function object 本身应该需要模板参数的任何可能原因。

Surely somewhere in boost or in the STL these versions exist?这些版本肯定存在于 boost 或 STL 中的某个地方吗? They are, of course, trivial to write, but I very much dislike duplicating library code, especially for something as apparently trivial as this.当然,它们写起来很简单,但我非常不喜欢复制库代码,尤其是对于像这样看似微不足道的东西。

EDIT :编辑

As some context as to why I would want this instead of using lambdas, or another function-object generation method:关于为什么我想要这个而不是使用 lambda 或其他函数对象生成方法的一些上下文:

I was writing a generic boost::fusion sequence comparison function thusly:我正在写一个通用的boost::fusion序列比较 function 因此:

template <class T>
bool sequence_equal(const T& left, const T& right)
{
    return fusion::all(
        fusion::zip(left, right),
        fusion::fused<generic_equal_to>());
}

Note the fusion::fused<generic_equal_to> part, which leads to the isse that you can't practically specify a boost::lambda or boost::phoenix function-object by type.请注意fusion::fused<generic_equal_to>部分,这导致您实际上无法按类型指定boost::lambdaboost::phoenix函数对象。 I guess one solution might be decltype:我想一个解决方案可能是 decltype:

fusion::fused<decltype(_1 == _2)>()

That seems very awkward though, and might not even work, depending on how boost::lambda or boost::phoenix is implemented - I'm really not sure.不过,这看起来很尴尬,甚至可能行不通,具体取决于boost::lambdaboost::phoenix的实现方式——我真的不确定。

I know you can use fusion::make_fused to get around this whole issue, but then you have to instantiate the function object. The solution I thought of, then, would be a non-template equal_to struct - I called mine generic_equal_to .我知道您可以使用fusion::make_fused来解决整个问题,但是您必须实例化 function object。然后,我想到的解决方案是非模板equal_to结构——我将我的命名为generic_equal_to

I know it's a very trivial problem - after all, make_fused(_1 == _2) will probably inline down to much the same assembly as fused<generic_equal_to> .我知道这是一个非常微不足道的问题——毕竟, make_fused(_1 == _2)可能会内联到与fused<generic_equal_to>大致相同的程序集。 I just couldn't believe that there was no generic_equal_to function object in boost or in the STL anywhere, hence this question.我简直不敢相信在任何地方都没有generic_equal_to function object 或 STL,因此出现了这个问题。

I don't think there's anything quite as direct as you're asking for, but there are utilities that not only cover your use-cases, but go beyond.我认为没有任何东西像您要求的那样直接,但有些实用程序不仅涵盖您的用例,还涵盖 go。 They are Boost.Lambda and Boost.Phoenix (the latter being a more generic successor to the lambda library).它们是Boost.LambdaBoost.Phoenix (后者是 lambda 库的更通用的继承者)。

Example using Boost.Lambda for generic equality:使用 Boost.Lambda 实现通用相等性的示例:

#include <boost/lambda/lambda.hpp>
#include <iomanip>
#include <iostream>

struct foo {};

bool operator==(foo, foo) { return true; }
bool operator==(foo, int) { return false; }

template <typename T, typename U, typename Func>
void f(const T& x, const U& y, Func func)
{
    std::cout << func(x, y) << std::endl;
}

int main()
{
    using namespace boost::lambda; // for placeholders
    std::cout << std::boolalpha;

    foo a, b;
    int i = 0;

    f(a, b, _1 == _2);
    f(a, i, _1 == _2);
}

And the same, with Phoenix:和凤凰一样:

#include <boost/phoenix.hpp>
#include <iomanip>
#include <iostream>

struct foo {};

bool operator==(foo, foo) { return true; }
bool operator==(foo, int) { return false; }

template <typename T, typename U, typename Func>
void f(const T& x, const U& y, Func func)
{
    std::cout << func(x, y) << std::endl;
}

int main()
{
    using namespace boost::phoenix::arg_names; // for placeholders
    std::cout << std::boolalpha;

    foo a, b;
    int i = 0;

    f(a, b, arg1 == arg2);
    f(a, i, arg1 == arg2);
}

Each of these can be extended to support the other operators in the obvious way (and more generally, into other expressions).这些中的每一个都可以以明显的方式扩展以支持其他运算符(更一般地,扩展到其他表达式中)。 I would personally go with Phoenix, because if you find out you need more functionality than lambda offers you won't end up including both.我个人会选择 go 和 Phoenix,因为如果你发现你需要比 lambda 提供的功能更多的功能,你最终不会同时包括两者。

Now in C++14 there is std::equal_to<void> (that can be also used as std::equal_to<> )现在在 C++14 中有std::equal_to<void> (也可以用作std::equal_to<>

std::equal_to<> is a specialization of std::equal_to with parameter and return type deduced. std::equal_to<>std::equal_to的特化,带有推导的参数和返回类型。

template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
  -> decltype(std::forward<T>(lhs) == std::forward<U>(rhs));

Returns the result of equality comparison between lhs and rhs.返回 lhs 和 rhs 相等比较的结果。

Docs 文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM