Кроссплатформенный способ создания boost :: function из указателя на функцию - PullRequest
0 голосов
/ 19 декабря 2011

Я писал несколько шаблонов, которые ожидают, что они будут переданы boost :: function.Они определяют аргументы для boost :: function, а затем используют их для создания соответствующей специализации класса.Например, это шаблон для 0 аргументов:

template< class ReturnT >
MyFunctionPtr MakeFunction( boost::function< ReturnT (  ) > func )
{
    return MyFunctionPtr( new MyFunction< decltype( func ), ReturnT >( func ) );
}

В качестве ярлыка я получил другую версию шаблона MakeFunction, которая принимает указатель на функцию и автоматически оборачивает его в повышение:: функция соответствующего типа:

template< class T >
MyFunctionPtr MakeFunctionFromPointer( T func )
{
    return MakeFunction( 
        boost::function< typename boost::remove_pointer<T>::type >( func )
        );
}

Это позволяет мне создавать из указателей функций без явной передачи спецификации функции:

int something() { return 1; }
MakeFunctionFromPointer( &something );

В MSVC это работает нормально, но с GCC4.3 Я получаю ошибки "нет подходящей функции".Похоже, что:

На MSVC boost::remove_pointer< bool (*)() >::type это bool ()

Но на GCC 4.3: boost::remove_pointer< bool (*)() >::type это bool ()()

Так что на GCC соответствующий шаблонMakeFunction не существует.

Можно ли каким-либо образом изменить выходные данные на выходе remove_pointer на любой платформе, чтобы они соответствовали другой?Или есть другой способ решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 19 декабря 2011

Вы можете создать шаблон функции создателя типа:

template <typename R>
boost::function<R()> make_function(R(*f)())
{ return boost::function<R()>(f); }

template <typename R, typename ...Args>
boost::function<R(Args...)> make_function(R(*f)(Args...))
{ return boost::function<R(Args...)>(f); }

Если ваш компилятор не поддерживает переменные шаблоны, вы можете использовать что-то вроде взлома препроцессора Microsoft для их моделирования (например, см. красивый исходный код принтера для примера).

1 голос
/ 19 декабря 2011

Вы можете явно взять указатель в качестве аргумента функции и вывести тип функции из этого:

template< class T >
MyFunctionPtr MakeFunctionFromPointer( T * func )
{
    return MakeFunction( boost::function<T>( func ) );
}

ОБНОВЛЕНИЕ: на основании вашего комментария ниже, похоже, проблема в том, что вы объявляете MakeFunction после , используя его в определении MakeFunctionFromPointer.Либо моя версия, либо ваша, использующая boost::remove_pointer, должна подойти, если все функции объявлены перед использованием.

...