Using Custom Unary Predicates With boost::mpl::find_if in C++

131 Views Asked by At

I have a number of different class types each with the member function GetParameterString() which returns a string specific to the class. I'd like to be able to store these class types in a boost::mpl::list and compare GetParameterString to a test string that I receive from another source. So if I have 3 class types, I'd like to do something like the following:

const std::string input_string = "Random String";

using ClassTypes = boost::mpl::list<ClassA, ClassB, ClassC>;
auto it = boost::mpl::find_if<ClassTypes>( [&input_string](auto next_class){
          return input_string.compare(next_class.GetParameterString() )
});
it->CallSomeOtherCommonClassMethod();

There are two problems here. First the return value is an int and not a bool. But more importantly, how I've set up the call to boost::mpl::find_if seems incorrect even if I return a bool.

One of my requirements here is to stick to boost::mpl. Thanks in advance!

2

There are 2 best solutions below

1
Eugene On

boost::mpl library is mostly compile-time-only, and it operates purely on types rather than values (boost::mpl::for_each is an exception). The result of its find_if is one of the classes, not a value of any type. "lambda" passed in it is not the usual C++ lambda either.

You may be able to achieve what you want if getParameterString() is static constexpr member function. You would need to figure out how to create the right type Predicate. Once you have that, your code should look like:

using ClassTypes = boost::mpl::list<ClassA, ClassB, ClassC>;
using iter = boost::mpl::find_if<ClassTypes, Predicate>::type;
boost::mpl::deref<iter>::type::CallSomeOtherCommonClassMethod();
1
Astris On

So I'm leaning towards believing that my use of boost::mpl::find_if is incorrect as opposed to not using boost::mpl as a complie-time-only library used on types. For reference, I use boost::mpl::for_each in in the following, without any issue and get exactly what I want:

boost::mpl::for_each<ClassTypes>([&input_string](auto next_class) {
     if (next_class.GetParameterString() == input_string) {
               // DO SOMETHING
     }});