Reputation: 3433
Is there any function objects in the boost that are generic equivalents to the std::equal_to, std::greater etc. family of function objects?
Essentially, std::equal_to should become something like
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). I can't see any possible reason why the std::equal_to function object itself should require a template argument, though.
Surely somewhere in boost or in the STL these versions exist? 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:
I was writing a generic boost::fusion
sequence comparison function thusly:
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. I guess one solution might be 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.
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
.
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>
. I just couldn't believe that there was no generic_equal_to
function object in boost or in the STL anywhere, hence this question.
Upvotes: 4
Views: 679
Reputation: 47640
Now in C++14 there is std::equal_to<void>
(that can be also used as std::equal_to<>
)
std::equal_to<>
is a specialization ofstd::equal_to
with parameter and return type deduced.
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.
Upvotes: 1
Reputation: 504103
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. They are Boost.Lambda and Boost.Phoenix (the latter being a more generic successor to the lambda library).
Example using Boost.Lambda for generic equality:
#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.
Upvotes: 1