Общий функтор для функций с любым списком аргументов - PullRequest
3 голосов
/ 29 января 2012

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

Я попытался преобразовать указатель функции во что-то вроде std :: function, и я получил ошибку:

error: invalid use of incomplete type ‘struct std::function<void (*)(...)>’
/usr/include/c++/4.6/functional:1572:11: error: declaration of ‘struct std::function<void(*)(...)>’

Я использую gcc4.6.1, компиляция с -std = c ++ 0x

Это минимальный пример:

#include <functional>

using namespace std;
typedef void (*F_vararg)(...);
class Foo
{
    public:
        template<typename... ARGS> Foo(function<F_vararg(ARGS... args)> f);
        ~Foo(){}
        template<typename... ARGS>void operator()(ARGS... args);
    private:
        F_vararg m_f;
};

template<typename... ARGS> 
Foo::Foo(function<F_vararg(ARGS... args)> f)
{
    m_f = f;
}

template<typename... ARGS>
void Foo::operator()(ARGS... args)
{
    m_f(args...);
}

void func1(double *a1, double *a2, double *b)
{    //do something 
}

int main(void)
{
    Foo func1_functor((std::function<void (*)(...)>)(func1));

    double a1[3] = {2.,3.,4.};
    double a2[3] = {2.2,3.2,4.2};
    double b[3] = {1.5,2.5,3.5};

    func1_functor(a1,a2,b);

    return 0;
}

Это НЕ компилируется ... Если я не объявляю конструктор какшаблон, но с "F_vararg f" в качестве аргумента и соответствующим образом отрегулировать приведение в экземпляре, он работает (не так ли?), но у меня нет шансов (?) получить какую-либо информацию об аргументах func1 в конструкторефунктор, который мне нужен.

Я что-то упустил?Есть ли другой способ сделать это?

Заранее спасибо !!!

ура, Штеффен

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

Я посмотрел на std :: bind, но не мог придумать, как добиться того, чего я хочу ...

Ответы [ 2 ]

10 голосов
/ 29 января 2012

Потерять typedef.Функция, которая принимает переменные аргументы, является специфическим типом, она не совместима с функциями, принимающими типизированные аргументы, и ей нельзя указывать типы параметров позже.

Это должно работать вместо:

template<typename... ARGS> Foo(function<void(*)(ARGS... args)> f);

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

#include <functional>

template<typename... ARGS>
class Foo
{
    std::function<void(ARGS...)> m_f;
public:
    Foo( std::function<void(ARGS...)> f ) : m_f(f) {}
    void operator()(ARGS... args) const { m_f(args...); }
};

template<typename... ARGS>
Foo<ARGS...> MakeFoo(void(*f)(ARGS...)) { return Foo<ARGS...>(f); }

void func1(double *a1, double *a2, double *b)
{    //do something 
}

int main(void)
{
    auto func1_functor = MakeFoo(func1);

    double a1[3] = {2.,3.,4.};
    double a2[3] = {2.2,3.2,4.2};
    double b[3] = {1.5,2.5,3.5};

    func1_functor(a1,a2,b);

    return 0;
}

Демо: http://ideone.com/fnUg2

3 голосов
/ 29 января 2012

Чтобы быть безопасным для типа, Foo также должен кодировать тип аргументов.Вопрос не определяет вариант использования полностью, поэтому я не уверен, требуется ли иметь возможность передавать «несвязанные» Foos и при этом каждый из них как-то запоминает (во время выполнения), какие типы его аргументов,В любом случае, этот код будет работать с примером, приведенным в qeuration.

#include<utility>

template<typename FunctionType>
struct Foo {
        FunctionType f;
        Foo(FunctionType f_) : f(f_) {}

        template<typename... Args>
        void operator() (Args&&... args) {
                f(  std::forward<Args>(args)... );
        }
};

template<typename FunctionType>
Foo<FunctionType> foo(FunctionType f) {
        return Foo<FunctionType>(f);
}

void func1(double *, double *, double *)
{    //do something 
}


int main() {
        auto x = foo(func1);
        double d[3] = {2,3,4};
        func1(d, d, d);
        x(d, d, d);
}
...