Я ищу путь в C++ для извлечения типа возврата функции (не называя его). Я предполагаю, что это потребует некоторого шаблонного волшебства.
float Foo();
int Bar();
magic_template<Foo>::type var1; // Here 'var1' should be of type 'float'
magic_template<Bar>::type var2; // and 'var2' should be of type 'int'
Я в настоящее время занимаюсь расследованиями как magic_template
мог бы быть реализован, но не нашли решение до сих пор.
Какие-либо идеи?
Это сложно, потому что имена функций являются выражениями, а не типами - нужно что-то вроде gcc's typeof
. Boost's TypeOf является портативным решением, которое становится очень близким.
Однако, если код можно организовать так, чтобы работа велась внутри шаблона функции, к которой можно передать Foo
или Bar
, то есть прямой ответ:
template <class R>
void test(R (*)())
{
R var1;
}
int main()
{
test(&Foo);
}
Взгляните на библиотеку boost traits типа, в частности, шаблон function_traits
предоставляет такую функциональность вне коробки. Если вы не можете использовать boost, просто скачайте код и прочитайте исходники, чтобы понять, как это делается.
Обратите внимание, что функциональность основана на типах, а не на конкретных функциях, поэтому вам может понадобиться добавить туда какой-нибудь лишний код.
После небольших тестов это может быть не то, что вам действительно нужно, а если это 'какой-нибудь лишний код', то он будет нетривиален. Проблема в том, что шаблон function_traits
работает на сигнатурах функций, а не на реальных указателях на функции, так что проблема изменилась с 'get the return type from a function pointer' на 'get the signature from a function pointer', что, наверное, самая сложная часть там.
Как подсказывают dribeas, вот решение, к которому я в итоге пришел:
float Foo();
int Bar();
template<typename T> Monkey(T) {
boost::function_traits< boost::remove_pointer<T>::type >::result_type var1 = ...;
// Now do something
}
Monkey(Foo);
Monkey(Bar);
Это не совсем та форма, к которой я стремился с моим оригинальным вопросом, но она достаточно близка мне.
.Foo и Bar - функции, а не типы функций, поэтому нужно немного поработать.
Вот решение, использующее комбинацию boost::function_traits и BOOST_TYPEOF.
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits.hpp>
float Foo();
int Bar();
int main()
{
boost::function_traits<BOOST_TYPEOF(Foo)>::result_type f = 5.0f;
boost::function_traits<BOOST_TYPEOF(Bar)>::result_type i = 1;
return i;
}
Edit:
Попробуйте что-нибудь подобное:
template<class T> struct magic_template
{};
template<class T> struct magic_template<T()>
{
typedef T type;
};
В C++ 0x используйте decltype
.
Для обсуждения проблем и попытки построить решение для более раннего стандарта Си++ смотрите здесь:
Скотт Майерс "бросает вызов" (PDF) и Андрей Александреску пытается решить его