Время выполнения находит первое совпадение в boost::mpl::vector

У меня есть boost::mpl::vector, и теперь мне нужен шаблон (функция), который "перебирает" типы до тех пор, пока не будет найдено первое совпадение (во время выполнения). Что-то похожее на boost::fusion::find_if, но без sequence, являющегося значением времени выполнения.

Будет ли это работать так:

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);

Возможно ли что-то подобное в mpl/fusion (не нашел)


Я знаю, что все варианты Callback::operator() будут "созданны", но это нормально. Можно было бы реализовать это с помощью Variadic Templates, но, к сожалению, я застрял на C++98.


person abergmeier    schedule 27.03.2015    source источник
comment
Как этот вопрос не связан (или даже идентичен) с stackoverflow.com/q/24954220/85371?   -  person sehe    schedule 27.03.2015
comment
Это определенно связано с другим постом.   -  person abergmeier    schedule 28.03.2015


Ответы (1)


Я бы предложил объединить фильтр и обратный вызов в условную операцию:

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;
};

Тогда свободно после ответа Эрика Ниблера¹ можно написать:

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

Вот полная демонстрация

Жить на 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);
}

Печать

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

¹ boost::mpl::for_each без создания экземпляров

person sehe    schedule 27.03.2015
comment
Спасибо за указание на это, уже забыл о предыдущем посте :). Кажется, что в настоящее время он не прерывается, когда Finder<T> возвращает true в первый раз. И обратите внимание на ограничение C++98. Я постараюсь получить рабочую версию в понедельник. - person abergmeier; 28.03.2015