C ++
Я пытаюсь реализовать оболочку функции через (класс объекта) шаблон шаблона (variadic). Класс имеет в качестве своего единственного члена данных указатель функции, который инициализируется или присваивается указателю функции, который он переносит. Параметризованный конструктор берет указатель на функцию и инициализирует им член. operator()
Метод принимает аргумент (ы) (или ничего) и вызывает с ними упакованную функцию. По крайней мере, это идея. Я получаю много ошибок, которые отмечаю комментариями. VC11 (с CTP в ноябре 2012 года, чтобы включить вариадические шаблоны) дает мне 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
тип указателя на функцию или тип функции? Если это последнее, то я могу понять контекст сообщения об ошибке.
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;
}
};