Подтвердить что ты не робот

Оператор преобразования С++ для преобразования в указатель на функцию

Я замалчивал голову идеей, которая достаточно проста в моей голове, но я не могу понять, как реализовать на С++.

Обычно я могу объявить класс с оператором преобразования, как в этом простом примере:

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 такого типа. Это явно делает вещи намного более неуклюжими, но я надеюсь, что есть еще способ.

4b9b3361

Ответ 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
{
    // ...
}