генерация функтора из типа указателя функции-члена

Я пытаюсь упростить (через make_fn()) генерацию функторов, которые предварительно обрабатывают параметры (через wrap()) для функций-членов с арностью 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. У меня это работает с решением на основе макросов, но это решение требует явного указания типов и количества параметров.
Через разрешение перегрузки функции я надеюсь сгенерировать правильный функтор преобразования неявно из сигнатуры функции-члена.


person Georg Fritzsche    schedule 10.10.2009    source источник
comment
Чего вы на самом деле пытаетесь достичь? Что вы хотите упростить из привязки (boost/c++0x)? Кажется, что вам нужен шаблон, который принимает один аргумент, который является указателем на функцию-член, и создает функтор, который требует экземпляр и соответствующее количество аргументов без вмешательства пользователя (то есть без того, чтобы пользователь делал номер аргумента/ тип явный, это так?   -  person David Rodríguez - dribeas    schedule 10.10.2009
comment
Да, в основном мне нужен функтор с фиксированным числом аргументов, который обертывает функции-члены арности n и с произвольными типами.   -  person Georg Fritzsche    schedule 10.10.2009
comment
Мне кажется, что вы хотите вывести шаблон для параметра, не являющегося типом. F не является типом: это указатель на конкретную функцию-член, поэтому вы не можете выполнить make_fn(F f). Я не уверен, что это сработает: кажется, вы хотите создать шаблон из переменной указателя функции-члена во время выполнения.   -  person UncleBens    schedule 10.10.2009
comment
Но у функции-члена есть тип/подпись, и я тоже должен иметь возможность вычитать из этого? Вывод должен происходить во время компиляции. Boost bind, кажется, делает похожие вещи, но что касается подробностей их реализации, я не понимаю, как они это решили.   -  person Georg Fritzsche    schedule 10.10.2009
comment
Действительно ли boost использует нетиповые параметры шаблона? Представьте: bool (X::*mp)(Y) = rand() % 2 ? &X::foo : &X::bar; make_fn(mp); Чего именно вы ожидаете?   -  person UncleBens    schedule 10.10.2009
comment
Я переименую ваш X в T. Я ожидаю, что получу один функтор, который вызывает wrap‹T,Y,bool (T::*mp)(Y)›(T* t,X x) { return (t-› *mp)(процесс‹Y›(x)); }. .... Кстати, как вы делаете разметку в комментариях?   -  person Georg Fritzsche    schedule 10.10.2009
comment
И... я не мог понять, как именно буст работает в этом отношении, поэтому я не уверен. Если F не тип, то что такое тип F?   -  person Georg Fritzsche    schedule 10.10.2009
comment
Тип F — bool (C::*)(T1). Насколько я понимаю, вы могли бы ожидать wrap‹T, Y, &T::foo› или wrap‹T, Y, &T::bar›, но как один и тот же оператор может создать другой тип из значения времени выполнения?   -  person UncleBens    schedule 11.10.2009
comment
Но этот тип F безымянный, как мне получить к нему доступ? В качестве примечания: я не ожидаю динамических типов, я просто не хочу писать такие вещи, как wrap‹T,Y,&T::foo› явно или через макрос а-ля FUNCTION_1(T,&T::foo,Y ), когда он известен статически. Кстати, явное использование работает.   -  person Georg Fritzsche    schedule 11.10.2009


Ответы (1)


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

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

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

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

person UncleBens    schedule 10.10.2009
comment
Хотя я надеялся избежать создания еще одного функтора, это работает - спасибо :) Для шаблонов с псевдовариативными параметрами (мне это нужно в vc8) make_fn() может быть определен для всех необходимых аритетов. - person Georg Fritzsche; 11.10.2009