2012-04-09 44 views
4

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

我可以看到性病的仿制版本::加等可能是棘手由于与返回类型的问题(虽然decltype能解决这个问题)。尽管如此,我无法看到std :: equal_to函数对象本身应该需要模板参数的任何可能原因。

无论在boost还是在STL中,这些版本都存在?当然,它们是微不足道的,但是我非常不喜欢重复库代码,特别是对于像这样明显微不足道的东西。

编辑

由于一些背景,为什么我想这个,而不是使用lambda表达式,或者另一个函数对象生成方法:

我正是如此写一个通用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>部分,这导致了ISSE,你不能根据实际情况指定一个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中没有任何函数对象,所以这个问题。

+2

我想你的意思'运营商()(const的T&T,常量U&U)' – 2012-04-09 00:59:56

+1

+1,但我不认为你会找到一个支持的功能。这个问题很重要(我昨天刚刚写了这个代码[答案](http://stackoverflow.com/questions/10063037/unordered-set-storing-elements-as-pointers/10063081#10063081)),但它是没有足够的性感来吸引Boost开发者,而且std :: equal_to没有足够的突破,标准化委员会将会贬低它。 – Potatoswatter 2012-04-09 01:36:02

+0

@ AndrewTomazos-Fathomling哈哈!试图写代码没有计算机来检查我的语法*总是*让我上某处 – Ayjay 2012-04-09 01:41:00

回答

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

每一种可扩展,以支持在明显的方式其他运营商(更一般地说,转换成其他表达方式)。我个人会和Phoenix一起去,因为如果你发现你需要比lambda提供的更多功能,那么你最终不会包括这两者。

+0

是的,我意识到生成函数对象的其他方式,但我的问题的整个观点是平凡的操作是否已经在某处定义。它们是,但它们都是在'struct'而不是'operator()'上模板化的。 – Ayjay 2012-04-09 08:03:14

+0

刚刚添加了一些基本原理,为什么我不愿意使用'boost :: lambda'或'boost :: phoenix'。 – Ayjay 2012-04-09 08:16:09

+0

@Ayjay:只要使用'make_fused'。他们不会手动实现stdlib的东西,如果他们已经有更多的公用事业。 – GManNickG 2012-04-09 15:53:27

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