генерация функтора по типу указателя на функцию-член - PullRequest
5 голосов
/ 10 октября 2009

Я пытаюсь упростить (через make_fn()) генерацию функторов, которые предварительно обрабатывают параметры (через wrap()) для функций-членов arity n .
Генерация функторов в основном работает, но до сих пор только путем явного указания типов параметров для функции-члена.
Теперь я хотел бы сгенерировать правильный функтор из типа функции-члена, которую он обрабатывает:

struct X {};

template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
bool wrap(C* c, X x) 
{
    return (c->*F)(process<T1>(x));
}

template<class C, typename T1, bool (C::*F)(T1)> 
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(F f) // <- problem here, F is not a type
{
    return boost::bind(&wrap<C, T1, F>, _1, _2);
}

Однако при этом vc ++ и g ++ не видят F как тип для параметра make_fn(). Я должен пропустить что-то очевидное здесь и чувствую себя немного слепым.

Идея заключалась в том, что это должно работать так:

struct A 
{
    bool f1(bool) { return true; }
};

void test()
{
    A a;
    X x;
    make_fn(&A::f1)(&a, x);
}

Есть идеи, как заставить это работать?

Справка:
У меня есть фиксированный интерфейс, который при упрощении выглядит следующим образом:

bool invoke(C* c, const char* const functionName, int argCount, X* args);

X - это вариантный тип, который мне нужно преобразовать в определенные типы бэкэнда (int, std :: string, ...).
Для обработки этих вызовов у меня есть карта функторов, которые ищутся по имени, и сопоставляют эти вызовы с функциями-членами некоторого экземпляра.
Цель упаковки - избежать ручных преобразований и вместо этого генерировать функторы, которые выполняют преобразование для меня или throw. Я работаю с решением на основе макросов, но это решение требует явного указания типов и количества параметров.
Через разрешение перегрузки функции я надеюсь создать неявный функтор преобразования неявно из сигнатуры функции-члена.

1 Ответ

3 голосов
/ 11 октября 2009

Мне кажется, что вы пытаетесь превратить указатель, переданный функции, в нетипичный аргумент шаблона, который, боюсь, не сработает (см. Комментарии к вашему вопросу).

Что вы можете сделать, это сохранить указатель функции в объекте функции. Появляется следующее для компиляции:

#include <boost/bind.hpp>
#include <boost/function.hpp>

struct X {};

template <class T>
bool process(X) { return true; }


template <class C, class T1, class Func>
struct wrap1
{
    typedef bool result_type;
    Func f;

    wrap1(Func f): f(f) {}

    bool operator()(C* c, X x)
    {
        return (c->*f)(process<T1>(x));
    }
};

template<class C, typename T1>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(bool (C::*f)(T1))
{
    return boost::bind(wrap1<C, T1, bool (C::*)(T1)>(f), _1, _2);
}


struct A
{
    bool f1(bool) { return true; }
};

void test()
{
    A a;
    X x;
    make_fn(&A::f1)(&a, x);
}

Однако я не уверен, насколько это хорошо, и как бы вы создали остальные обертки. Для последнего вы можете просто получить компилятор, который поддерживает шаблоны с переменным числом аргументов. :)

...