Оператор преобразования С++ для преобразования в указатель на функцию
Я замалчивал голову идеей, которая достаточно проста в моей голове, но я не могу понять, как реализовать на С++.
Обычно я могу объявить класс с оператором преобразования, как в этом простом примере:
class Foo
{
private:
int _i;
public:
Foo( int i ) : _i(i) { }
operator int( ) const
{
return i;
}
};
Итак, теперь я могу написать потрясающий материал, например
int i = Foo(3);
Но в моем конкретном случае я хотел бы предоставить оператор для преобразования объекта в указатель функции (например, преобразование экземпляра Bar
в указатель функции int(*)(int, int)
). Вот что я изначально пробовал:
class Bar
{
private:
int (*_funcPtr)(int, int);
public:
Bar( int (*funcPtr)(int, int) ) : _funcPtr(funcPtr) { }
operator int(*)(int, int) ( ) const
{
return _funcPtr;
}
};
Но операторная функция не скомпилируется с генерированием этих ошибок:
expected identifier before '*' token
'<invalid-operator>' declared as a function returning a function
Я также пробовал простые варианты выше, такие как окружающий тип возврата в скобках, но все эти идеи также потерпели неудачу.
Кто-нибудь знает, что такое синтаксис для объявления метода оператора-указателя-преобразования-указателя или можно ли это сделать?
Примечание. Я компилирую это с помощью Code:: Blocks, используя GCC 4.5.2. Также приветствуются ответы на некоторые из новых концепций С++ 0x.
Изменить
В моей стремлении упростить пример, я непреднамеренно оставил одну деталь. Это немного странно, но вместо того, чтобы строго возвращать указатель int(*)(int,int)
, оператор преобразования предназначен для шаблонов:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
// implementation is unimportant here
}
Насколько я знаю, я больше не могу typedef такого типа. Это явно делает вещи намного более неуклюжими, но я надеюсь, что есть еще способ.
Ответы
Ответ 1
Поскольку вы должны знать:
(*operator int() const)(int, int)
{
return _funcPtr;
}
(Исправлено.).
Обновление: Мне сообщили Йоханнес Шрауб и Люк Дантон, что этот синтаксис на самом деле недействителен и что вы действительно должны использовать typedef. Поскольку вы говорите, что typedefs не вариант, вот вспомогательный класс, который может обернуть ваш typedef:
template<typename R, typename A1, typename A2>
struct MakeFunctionType
{
typedef R(*type)(A1, A2);
};
template<typename R, typename A1, typename A2>
operator typename MakeFunctionType<R, A1, A2>::type () const
{
// implementation is unimportant here
}
Ответ 2
Используйте typedef. Во всяком случае, это легче читать:
class Bar
{
public:
typedef int (*fptr_t)(int, int);
Bar(fptr_t funcPtr) : _funcPtr(funcPtr) { }
operator fptr_t() const
{
return _funcPtr;
}
private:
fptr_t _funcPtr;
};
[править]
В случае с шаблоном я не вижу, как использовать typedef. @Kerrik дает (беспорядочную) версию синтаксиса, который должен работать.
Ответ 3
EDIT:
Так как ваш класс имеет указатель функции без шаблона, назначенный в constuction:
private:
int (*_funcPtr)(int, int);
Невозможно позже преобразовать это в указатель на функцию любого типа.
Поэтому я предполагаю, что вы имели в виду перегрузку оператора члена класса шаблона, а не перегрузку оператора элемента шаблона класса.
Версия шаблона:
template<typename ReturnType, typename ArgType1, typename ArgType2>
class Bar {
public:
typedef ReturnType (*fptr_t)(ArgType1, ArgType2);
operator fptr_t ( ArgType1 arg1, ArgType2 arg2 ) const
{
// implementation is unimportant here
}
//etc...
};
Затем используется так:
//create functor to some function called myfunc
Bar::fptr_t func_ptr = Bar<int, int, int>(&myfunc);
//call functor
int i = func_ptr(1,2);
Ответ 4
Если вы хотите сделать код читаемым, вам нужно использовать typedef. Я даже не использую указатели функций без их typedef's, синтаксис слишком ужасен.
Цель:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
return 0;
}
Path:
// 1: helper structure
template <typename R, typename A0, typename A1>
struct helper {
typedef R (*type)(A0,A1);
};
// 2: operator
template <typename R, typename A0, typename A1>
operator typename helper<R, A0, A1>::type() const {
return 0;
}
Проверьте это на ideone!
Ответ 5
В GCC работает следующее:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator decltype((ReturnType(*)(ArgType1, ArgType2)) nullptr)() const
{
// ...
}