1

I have a boost::mpl::vector and now would need a template (function), which "iterates" over the types until the first match (at runtime) is found. Something similar to boost::fusion::find_if, but without sequence being a runtime value.

Would image it to work like this:

typedef boost::mpl::vector<Foo, Bar> Types;

template< typename T >
struct Finder {
  bool operator()() const;
};

struct Callback {
  template< typename T >
  void operator()();
};

Callback callback;

magic_find_if<Types, Finder>(callback);

Is something like this already possible in mpl/fusion (could not find it)


I know, that all variants of Callback::operator() would be "instantiated" but this is ok. Could imagine to implement this with Variadic Templates, but sadly am stuck with C++98.

abergmeier
  • 13,224
  • 13
  • 64
  • 120

1 Answers1

1

I'd suggest combining the filter and callback into a conditional operation:

template <template<typename> class Finder, typename Callback>
struct ConditionOperation {
    ConditionOperation(Callback cb = {}) : _callback(std::move(cb)) 
    { }

    template <typename T>
    void operator()(boost::type<T>) const {
        if (Finder<T>()())
            _callback.template operator()<T>();
    }

private:
    Callback _callback;
};

Then, freely after the answer by Eric Niebler¹ you can write:

ConditionOperation<Finder, Callback> op;
mpl::for_each<Types, boost::type<mpl::_1> >(op);

Here's a full demo

Live On Coliru

#include <boost/type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <iostream>

struct Foo { enum { id = 879 }; };
struct Bar { enum { id = 321 }; };
struct Qux { enum { id = 555 }; };
typedef boost::mpl::vector<Foo, Bar, Qux> Types;

template <typename T>
struct Finder {
  bool operator()() const { return T::id > 500; }
};

struct Callback {
    template<typename T> void operator()() const {
        std::cout << __PRETTY_FUNCTION__ << "\n";
    }
};

template <template<typename> class Finder, typename Callback>
struct ConditionOperation {
    ConditionOperation(Callback cb = {}) : _callback(std::move(cb)) 
    { }

    template <typename T>
    void operator()(boost::type<T>) const {
        if (Finder<T>()())
            _callback.template operator()<T>();
    }

private:
    Callback _callback;
};

int main() {
    using namespace boost;

    ConditionOperation<Finder, Callback> op;
    mpl::for_each<Types, boost::type<mpl::_1> >(op);
}

Printing

void Callback::operator()() const [with T = Foo]
void Callback::operator()() const [with T = Qux]

¹ boost::mpl::for_each without instantiating

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for pointing that out, already forgot about the older post :). It seems like it currently does not abort, when `Finder` returns true the first time. And note the C++98 constraint. I will try to get a version working on Monday. – abergmeier Mar 28 '15 at 10:05