std algorithms with pointer to member as comparator/"key" - c++

I often find myself using std::sort, std::max_element, and the like with a lambda that simply invokes a member function
std::vector<MyType> vec;
// populate...
auto m = std::max_element(std::begin(vec), std::end(vec),
[](const MyType& a, const MyType& b) { return a.val() < b.val()})
this feels like a waste of characters and a loss of clarity. I'm aware that I could write another function/callable and pass a function pointer/callable object to these algorithm functions, but I often need to do this sort-by just once in a program and it doesn't strike me as a good way of addressing the problem. What I want to do, ideally is say:
auto m = std::max_element(std::begin(vec), std::end(vec), &MyType::val);
and have the objects be sorted by their val()s. Is there some part of the stdlib I'm overlooking that could assist me with this? or another simple way of doing it? I'd like to make what this is sorting or searching by as obvious as possible.
I'm aware that just &MyType::val isn't enough, I am looking for something that could perhaps wrap it, or provide a similar functionality without obscurring the meaning.

You can use std::mem_fn (or std::tr1::mem_fn)
int main()
{
std::vector<MyType> vec;
auto m = std::max_element(std::begin(vec), std::end(vec), compare_by(std::mem_fn(&MyType::field)));
}
Of course, this assumes that you have a utility like compare_by in your toolbox (as you should :)):
template <typename F>
struct CompareBy {
explicit CompareBy(F&& f) : f(std::forward<F>(f)) {}
template <typename U, typename V>
bool operator()(U const& u, V const& v) const {
return f(u) < f(v);
}
private:
F f;
};
template <typename F>
CompareBy<F> compare_by(F&& f) { return CompareBy<F>(std::forward<F>(f)); }
See it Live On Coliru

You can do it without introducing any new functions (templated or not).
Just use bind and std::less
auto m = std::max_element(vec.begin(), vec.end(),
bind(less<>(), bind(&MyType::val, _1), bind(&MyType::val, _2)));

A templated comparator could help you:
template <typename StructureType,
typename MemberType,
MemberType StructureType::*member>
bool comparator(const StructureType& the_first, const StructureType& the_second)
{
return the_first.*member < the_second.*member;
}
http://ideone.com/K8ytav
A bit of type traits magic could certainly allows you to avoid writing the type.

How about once overloading operator< for your custom type? This can be naturally done inside the class (or directly next to it), and then no further argument is required beside the iterators.
Passing your val() function isn't possible, as you must pass a binary operator.
EDIT: Having read the other valuable alternatives (also sehe's nice response), I want to confirm what I already mentioned in the comment below: In my opinion, nothing beats the readibility, locality and also flexibility of a lambda expression (--on the risk of writing some passages twice).
#Ryan Haining: I suggest you to keep it as in your original post.

An improvement on sehes answer, so as to avoid needing to use std::mem_fn would be provide a pointer to member overload for the compare_by function.
example usage
std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field));
std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field, std::greater<>{}));
the code to implement
#include <functional> // std::less
#include <utility> // std::move
#include <type_traits> // std::is_invocable_r
// Forward declaration
template<typename R, typename T, typename F = std::less<R>>
auto compare_by(R T::*, F = F{});
// Implementation
namespace detail {
template<typename T, typename F>
struct compare_by_t;
template<typename R, typename T, typename F>
struct compare_by_t<R T::*, F> : private F
{
compare_by_t(F&& f, R T::*m): F{std::move(f)}, _member{m} {}
R T::* _member;
bool operator()(T const& x, T const& y) const
{
return F::operator()(x .* _member, y .* _member);
}
};
} // detail
template<typename R, typename T, typename F>
auto compare_by(R T::* member, F f)
{
static_assert(std::is_invocable_r<bool, F, R, R>::value);
return detail::compare_by_t<R T::*, F>{ std::move(f), member };
}

Related

Construct a std::mem_fn by type

Consider this contrived example:
template<typename Fn, typename Iter, typename T>
void funny_transform(Iter first, Iter last, vector<T>& v)
{
transform(first, last,
back_inserter(v),
Fn());
}
Normally we would pass in the functor object directly, but this example is contrived to simulate the behavior of many STL containers. For example, std::map can take the type of the comparator and default-construct it, instead of taking a comparator object directly. (My actual use case is with some stateless functor class. Since the class is stateless, I can only pass in types.)
The problem is with std::mem_fn. If I try to do something like:
auto get_size = mem_fn(&string::size);
vector<string> v1 = { ... };
vector<string::size_type> v2;
funny_transform<decltype(get_size)>(v1.cbegin(), v1.cend(), v2); // oops
This won't work, because decltype(get_size) (whatever it is) does not have a default constructor. Though strangely it has copy and move constructors. Switching to a simple lambda won't work either, for exactly the same reason.
Do I have to write my own functor struct to work around this problem? Is there any standard library tool that I can use?
template<class F>
F& magic_store(F* f) {
static const F r=std::move(*f);
return r;
}
template<class F>
struct stateless_t{
stateless_t(F&&f){ magic_store<F>(&f); }
stateless_t()=default;
template<class...Args>
decltype(auto) operator()(Args&&...args)const{
return magic_store<F>(nullptr)(std::forward<F>(f));
}
};
template<class F>
stateless_t<F> make_stateless(F f){ return std::move(f); }
Now you can do
auto get_size = make_stateless([](auto&s){return s.size();});
vector<string> v1 = { ... };
vector<string::size_type> v2;
funny_transform<decltype(get_size)>(v1.cbegin(), v1.cend(), v2); // works
Note that this is a horrible hack, but standard legal. It is easily abused and easy to screw up non-locally. Only use it with a lambda that is already stateless. Never anything else.
In C++17 you could write:
template<auto F>
struct stateless_invoker{
template<class...Args>
decltype(auto) operator()(Args&&...args) const{
return std::invoke( F, std::forward<Args>(args)... );
}
};
which gives you:
using get_size = stateless_invoker<&std::string::size>;
vector<string> v1 = { ... };
vector<string::size_type> v2;
funny_transform<get_size>(v1.cbegin(), v1.cend(), v2); // works
which is less hacky. This can be reproduced in C++11 but is ugly.
Based on #Yakk 's idea, a simple workaround in C++14 can look something like this:
template<typename PMF, PMF pmf>
struct my_mem_fn_t {
template<typename... Args>
constexpr decltype(auto) operator()(Args&&... args) const
noexcept(noexcept(std::mem_fn(pmf)(std::forward<Args>(args)...)))
{
return std::mem_fn(pmf)(std::forward<Args>(args)...);
}
};
// well, if you really want to use macro
#define my_mem_fn(pmf) my_mem_fn_t<decltype(pmf), pmf>()
Then:
auto get_size = my_mem_fn_t<decltype(&string::size), &string::size>;
// or: my_mem_fn(&string::size);
string s("hello");
cout << decltype(get_size)()(s) << '\n'; // prints 5

Get type from a templated range

TL;DR
Given R as a template argument, for R being some_container<T> or T[], how to deduce T?
Possible implementation is std::iterator_traits<decltype(std::begin(r))>::value_type, looking for something less verbose.
Elaborated
I'm trying to implement a wrapper around std::accumulate algorithm, so that instead of typing this:
std::accumulate(v.begin(), v.end(), 0, [](int x, int y) { return x * y; });
user can simply write this:
my::accumulate(v, [](int x, int y) { return x * y; });
So basically, my::accumulate, given an entity and an operation, is intended to call std::accumulate with the following arguments:
std::begin() from the given entity
std::end() from the given entity
default-constructed value as a starting point
given operation
I use free begin and end functions to allow function work on built-in arrays. The passed entity is thus a range. Here is my implementation:
template<class R, typename F>
auto accumulate(const R& r, F&& f) ->
typename std::iterator_traits<decltype(std::begin(r))>::value_type
{
using T = std::iterator_traits<decltype(std::begin(r))>::value_type;
return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}
It works fine. The only thing that bothers me is that ugly std::iterator_traits<decltype(std::begin(r))>::value_type construction. Is there a better way to get the type from the range? Note that R does not have to be a container, so I cannot use R::value_type.
Please note, that I'm using Visual Studio 2013, so I can use most of C++11 and some of C++14.
PS. Any other comments on the implementation? Are there any drawbacks or implications?
You could use typename std::remove_reference_t<decltype(*std::begin(r))> to save a few keystrokes, but it isn't much better.
I suppose you want to implement more algorithms than just accumulate, in which case you can create an alias for the element type:
template<typename T>
using value_type = typename std::iterator_traits<decltype(std::begin(T{}))>::value_type;
template<class R, typename F>
value_type<R> accumulate(const R& r, F&& f)
{
return std::accumulate(std::begin(r), std::end(r), value_type<R>{}, std::forward<F>(f));
}
Otherwise, you could use a placeholder return type to avoid the repetition:
template<class R, typename F>
auto accumulate(const R& r, F&& f)
{
using T = typename std::iterator_traits<decltype(std::begin(r))>::value_type;
return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}

C++ overloading by functor param count type

I am working on "LINQ to Objects" library for C++11.
I would like to do smth like this:
// filtering elements by their value
arr.where( [](double d){ return d < 0; } )
// filtering elements by their value and position
arr.where( [](double d, int i){ return i%2==0; } )
I down want to write arr.where_i( ... ) - it's ugly.
So i need function/method overloading by lambda-type...
This is my solution:
template<typename F>
auto my_magic_func(F f) -> decltype(f(1))
{
return f(1);
}
template<typename F>
auto my_magic_func(F f, void * fake = NULL) -> decltype(f(2,3))
{
return f(2,3);
}
int main()
{
auto x1 = my_magic_func([](int a){ return a+100; });
auto x2 = my_magic_func([](int a, int b){ return a*b; });
// x1 == 1+100
// x2 == 2*3
}
Is it SFINAE solution?
What can you suggest me?
Maybe something variadic:
#include <utility>
template <typename F, typename ...Args>
decltype(f(std::declval<Args>()...) my_magic_func(F f, Args &&... args)
{
return f(std::forward<Args>(args)...);
}
Edit: You can also use typename std::result_of<F(Args...)>::type for the return type, which does the same thing.
You certainly want SFINAE in your solution. Generally speaking, the result would look something like:
template<
typename Functor
, typename std::enable_if<
special_test<Functor>::value
, int
>::type = 0
>
return_type
my_magic_func(Functor f);
template<
typename Functor
, typename std::enable_if<
!special_test<Functor>::value
, int
>::type = 0
>
return_type
my_magic_func(Functor f);
such that only one overload would be active at any one time -- all that remains now is carefully crafting that special_test to have the behaviour we want. This is a careful balancing act as you don't want the test to be too specific; otherwise we lose generality. Quite a shame when writing generic code. You haven't given too much information (e.g. are you strictly interested in support for lambdas? monomorphic functors? polymorphic functors?), but I will assume for now that we have access to a value_type alias which would correspond to double in your example.
As such, here's an example condition that will check that a given type is Callable (that's a Standard concept) with signature bool(value_type); i.e. that it's a predicate of sorts:
template<typename Functor, typename ValueType>
struct is_unary_predicate {
typedef char (&accepted)[1];
typedef char (&refused)[2];
void consume(bool);
template<
typename X
, typename Y
, typename = decltype( consume(std::declval<X>()(std::declval<Y>())) )
>
accepted
test(X&&, Y&&);
refused test(...);
static constexpr bool value =
sizeof test(std::declval<Functor>(), std::declval<ValueType>())
== sizeof(accepted);
};
Personally I have an is_callable<F, Signature> trait so that I would only need to write something like template<typename Functor, typename ValueType> using is_unary_predicate = is_callable<Functor, bool(ValueType)>; (and similarly I could have an is_binary_predicate alias instead of letting the second overload of my_magic_func be a catch-all). Perhaps you'd want to use a similar trait for future uses of SFINAE (although it may be somewhat painful to write without variadic templates).

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?
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.
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.
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 of std::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.
Docs

Generic way of getting const-qualification of elements from container

I need a generic function that can take either a const or non-const reference to a container, and return the corresponding reference to elements qualified as per the container.
Something along these lines:
template <typename C>
auto get_nth( C& c, int i ) -> /* not-sure-what, but let's call it T */
{
//.... some tricky code here ...
}
I would like to stress that if C expands to
SomeContainer const
then T would be
SomeContainer::const_reference
and otherwise
SomeContainer::reference
I think I can put it together using type traits and mtl if, my question is if there is a shorter, cleaner way.
I'm using C++x11 (obviously) and boost.
Thanks in advance.
I think you are looking for typename C::reference, see 23.2.1 [container.requirements.general] ยง4.
Oh wait, the above doesn't work if C is already const. But wait, decltype to the rescue!
template <typename C>
auto get_nth( C&& c, int i ) -> decltype(*c.begin())
{
//.... some tricky code here ...
}
If you also want to support C-style arrays which have no begin member function:
#include <iterator>
template <typename C>
auto get_nth( C&& c, int i ) -> decltype(*std::begin(c))
{
//.... some tricky code here ...
}
And the implementation really isn't that tricky:
#include <iterator>
template <typename C>
auto get_nth( C&& c, int i ) -> decltype(*std::begin(c))
{
auto it = std::begin(c);
std::advance(it, i);
return *it;
}
Note that the above solution accepts lvalues and rvalues, but it will always return an lvalue reference. Depending on the client code, this may be a performance concern. Take the following example code:
std::string s = get_nth(std::vector<std::string> { "hello", "world" }, 0);
This will copy the result into s, even though moving it would be perfectly valid (and, of course, faster).
To solve this problem, we need two overloads, one for lvalues and one for rvalues:
#include <iterator>
#include <type_traits>
template <typename C>
auto get_nth( C& c, int i ) -> decltype(*std::begin(c))
{
auto it = std::begin(c);
std::advance(it, i);
return *it;
}
template <typename C>
auto get_nth( C&& c, int i )
-> typename std::enable_if<std::is_rvalue_reference<C&&>::value,
decltype(std::move(*std::begin(c)))>::type
{
auto it = std::begin(c);
std::advance(it, i);
return std::move(*it);
}
Now the result will be moved into s. The enable_if part is necessary because due to reference collapsing rules, C&& can also bind to lvalues, and then the call to initialize s would be ambiguous.