Обертка функции через (класс объекта) шаблон класса (variadic)

C++

Я пытаюсь реализовать оболочку функции через (класс объекта) шаблон шаблона (variadic). Класс имеет в качестве своего единственного члена данных указатель функции, который инициализируется или присваивается указателю функции, который он переносит. Параметризованный конструктор берет указатель на функцию и инициализирует им член. operator() Метод принимает аргумент (ы) (или ничего) и вызывает с ними упакованную функцию. По крайней мере, это идея. Я получаю много ошибок, которые отмечаю комментариями. VC11 (с ноябрьским 2012 CTP, чтобы включить вариадические шаблоны) дает мне error C2091: function returns function во всех, кроме одной из отмеченных областей. Последняя ошибка отличается, и я комментирую ее полное описание в коде. G ++ дает в основном те же ошибки, хотя и с разными кодовыми номерами.

#include <iostream>

template <typename R, typename... Tn>
class func
{
    R (*fptr)(Tn...); // C2091
public:
    func() : fptr(nullptr) {}
    func( R (*f) (Tn...) ) : fptr(f) {} // C2091
    R operator()(Tn... args)
    { // C2091
        return fptr(args...);
    }
    func& operator=( R (*f) (Tn...) ) // C2091
    {
        fptr = f;
        return *this;
    }
};

int foo(int a, int b)
{
    std::cout << "foo\n";
    return 0;
}

int main()
{
    func<int(int, int)> myfunc;
    myfunc = foo; // C2679: binary '=' : no operator found which takes
    // a right-hand operand of type 'int (__cdecl *)(int,int)' (or 
    // there is no acceptable conversion)
}

Почему я получаю эти ошибки? Например, я не вижу, как параметризованный конструктор возвращает что-либо, или как объявление члена данных возвращает что-либо. Разве декларация члена данных не является формой объявления указателя функции? Например, не int (*g)(int); объявить указатель, который указывает на функцию, которая принимает int и возвращает int?

Редактировать / Добавление:

Я вижу из ответов, что int(int, int) только один тип, и мне нужна частичная специализация, чтобы получить желаемый эффект. Но что вызывает ошибку в моем коде? Если я закомментирую myfunc = fooЯ все еще получаю другие ошибки. func<int(int, int)> myfunc; вызывает конструктор по умолчанию typename R инстанцируется int(int, int), а также typename... Tn становится пустым. Член данных R (*fptr)(Tn...); становится R (*fptr)();, а также fptr поэтому является указателем на функцию, которая указывает на функцию, которая принимает нулевые аргументы и возвращает R, Если R является int(int, int)то есть R тип указателя на функцию или тип функции? Если это последнее, то я могу понять контекст сообщения об ошибке.

3 ответа

Решение

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

template <typename> struct func;         // leave undefined

template <typename R, typename ...Args>
struct func<R(Args...)>                  // specialized for typename = R(Args...)
{
    // ...
};

Ваш класс параметризован возвращаемым значением и типами аргументов, изложенными отдельно. Но при создании экземпляра вы пытаетесь параметризовать его по типу функции, а std::function, Сделай это func<int, int, int> myfunc;, С этим изменением ваш код работает.

Вам нужна частичная специализация.

Вот рабочий пример:

template <typename T>
class func;

template <typename R, typename... Tn>
class func<R(Tn...)> {
    typedef R (*fptr_t)(Tn...);
    fptr_t fptr;
public:
    func() : fptr(nullptr) {}
    func(fptr_t f) : fptr(f) {}
    R operator()(Tn... args) {
        return fptr(args...);
    }
    func& operator=(fptr_t f) {
        fptr = f;
        return *this;
    }
};
Другие вопросы по тегам