与std函数对象相同的泛型

时间:2012-04-09 00:34:58

标签: c++ templates generics boost stl

boost中是否有任何函数对象是std :: equal_to,std :: greater等系列函数对象的通用等价物?

基本上,std :: equal_to应该变成类似

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

我可以看到由于返回类型的问题,std :: plus等的泛型版本可能会更棘手(尽管decltype可以解决这个问题)。但是我看不出为什么std :: equal_to函数对象本身应该需要模板参数的任何可能的原因。

肯定在某些地方有提升或STL这些版本存在吗?当然,编写它们是微不足道的,但我非常不喜欢复制库代码,特别是对于像这样显然微不足道的东西。

修改

作为为什么我想要这个而不是使用lambdas或其他函数对象生成方法的一些上下文:

我正在编写一个通用的boost::fusion序列比较函数:

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

请注意fusion::fused<generic_equal_to>部分,这会导致您无法按类型实际指定boost::lambdaboost::phoenix函数对象。我猜一个解决方案可能是decltype:

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

这看起来很尴尬,甚至可能不起作用,具体取决于boost::lambdaboost::phoenix的实施方式 - 我真的不确定。

我知道你可以使用fusion::make_fused解决这个问题,但是你必须实例化函数对象。我想到的解决方案是非模板equal_to结构 - 我称之为generic_equal_to

我知道这是一个非常微不足道的问题 - 毕竟,make_fused(_1 == _2)可能会内联到与fused<generic_equal_to>相同的程序集。我无法相信boost或STL中没有generic_equal_to函数对象,因此这个问题。

2 个答案:

答案 0 :(得分:1)

我认为没有任何东西像你要求的那么直接,但是有些实用工具不仅涵盖了你的用例,而且超越了它。它们是Boost.LambdaBoost.Phoenix(后者是lambda库的更通用的继承者)。

使用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);
}

同样,凤凰城:

#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);
}

这些中的每一个都可以扩展为以显而易见的方式支持其他运算符(更一般地,支持其他表达式)。我个人会和凤凰城一起去,因为如果你发现你需要比lambda提供更多的功能,你最终不会同时包含这两种功能。

答案 1 :(得分:0)

现在在C ++ 14中有std::equal_to<void>(也可以用作std::equal_to<>

  

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));
  

返回lhs和rhs之间的相等比较结果。

Docs

相关问题