# Functional composition of member function predicates

In C++11, it is en vogue to use small lambda expressions to produce ad-hoc predicates. However, sometimes it's fun to create predicates in a functional, "point-free" way. That way, no function bodies need to be inspected, the code is mildly self-documenting, and it's a great icebreaker at parties.

Suppose I have a std::vector<std::vector<int>> v, and I want to remove all the empty inner vectors. The lambda-style remove_if call might look like this:

std::remove_if(v.begin(),
v.end(),
[](std::vector<int> const & w) -> bool { return w.empty(); });


This is verbose and redundant. The point-free approach uses std::mem_fn:

std::remove_if(v.begin(),
v.end(),
std::mem_fn(&std::vector<int>::empty));


This works fine. But now the problem: Suppose I want to further compose this predicate, say by negating it. In the lambda this would be a trivial change. But for the functional notation, we would like to use the library function std::not1 to produce a unary_negate wrapper.

However, the obvious std::not1(std::mem_fn(&std::vector<int>::empty)) does not compile. The problem appears to be that the result type of std::mem_fn defines its argument_type member type as a pointer to the class, not a reference; cf. 20.8.10/2:

The simple call wrapper shall define two nested types named argument_type and result_type as synonyms for cv T* and Ret, respectively, when pm is a pointer to member function with cv-qualifier cv and taking no arguments, where Ret is pm’s return type.

This breaks the composability with std::not1.

I have written this type mangling work-around which strips the unwanted pointer:

#include <type_traits>

template <typename T>
struct result_type_mangler : T
{
using argument_type = typename std::remove_pointer<typename T::argument_type>::type;
result_type_mangler(T t) : T(t) { }
};

template <typename T>
result_type_mangler<T> mangle(T t)
{
return result_type_mangler<T>(t);
}


Now I can compose the predicates:

std::not1(mangle(std::mem_fn(&std::vector<int>::empty)))


Is this a legitimate work-around? Can member function predicates be composed in an easier way? And why is the member function wrapper's argument_type defined in such a weird way?

• Note: bind also doesn't work: std::not1(std::bind(&std::vector<int>::empty, std::placeholders::_1)) Dec 23 '13 at 17:53
• Those parties sound fun! Dec 29 '13 at 8:58

The verbosity of C++14 generic lambdas should be much lower than std::mem_fun

std::remove_if(v.begin(),
v.end(),
[](auto const & w) { return w.empty(); });


If you want to remove non-empty vectors, you can also do something like

std::function<bool(std::vector<int>)> is_empty = [](auto const & w) { return w.empty(); };
std::remove_if(v.begin(),
v.end(),
std::not1(is_empty));


Oh and the -> bool in your question is already superfluous in C++11 for single-line lambdas. Generic lambdas are currently supported by Clang >= 3.4, GCC 4.9 and MSVC 2013 November CTP.

I think Scott Meyers even has an Item "Prefer lambdas over bind" in his upcoming book Effective C++11/14.

I think your way works, but there are other solutions:

In C++98, there is actually an std::mem_fun_ref function.
In C++11, there is the std::ref and std::cref functions.

// VS2012 doesn't have uniform initialization, so this is me being lazy
int a1 [] = {1, 2, 3, 4, 5} ;
int a2 [] = {6, 7, 8} ;

std::vector <int> v1 (std::begin (a1), std::end (a1)) ;
std::vector <int> v2 ;
std::vector <int> v3 (std::begin (a2), std::end (a2)) ;

std::vector <std::vector <int> > vv ;
vv.push_back (v1) ;
vv.push_back (v2) ;
vv.push_back (v3) ;

std::cout << vv.size () << std::endl ;

auto end = std::remove_if (std::begin (vv), std::end (vv), std::not1 (std::cref (&std::vector<int>::empty))) ;
vv.erase (end, std::end (vv)) ;

std::cout << vv.size () << std::endl ;


Update
It seems that using std::cref only works on Visual Studio. std::mem_fun_ref is a portable but deprecated solution. Therefore, I would say that your way is the best way out of these three solutions.

• That sounded interesting, but I can't reproduce that. With gcc, std::cref(&std::vector<int>::empty) is an error, e.g. see here. Maybe a VS weirdness? Dec 23 '13 at 17:49
• I looked over the reference_wrapper class implementation is Visual Studio 2012. It uses, what I believe is a universal reference in its constructor. I don't own a copy of the standard, but I'm assuming you're correct and that this is VS weirdness. std::mem_fun_ref seems to work, but that's a deprecated solution. Dec 23 '13 at 18:04