Извлеките тип возврата функции, не называя его (использующие шаблоны?)

Я ищу путь в 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 мог бы быть реализован, но не нашли решение до сих пор.

Какие-либо идеи?

8
задан Sergey K. 2 July 2012 в 13:26
поделиться

6 ответов

Это сложно, потому что имена функций являются выражениями, а не типами - нужно что-то вроде gcc's typeof. Boost's TypeOf является портативным решением, которое становится очень близким.

Однако, если код можно организовать так, чтобы работа велась внутри шаблона функции, к которой можно передать Foo или Bar, то есть прямой ответ:

template <class R>
void test(R (*)())
{
  R var1;
}

int main()
{
  test(&Foo);
}
5
ответ дан 5 December 2019 в 08:52
поделиться

Взгляните на библиотеку boost traits типа, в частности, шаблон function_traits предоставляет такую функциональность вне коробки. Если вы не можете использовать boost, просто скачайте код и прочитайте исходники, чтобы понять, как это делается.

Обратите внимание, что функциональность основана на типах, а не на конкретных функциях, поэтому вам может понадобиться добавить туда какой-нибудь лишний код.


После небольших тестов это может быть не то, что вам действительно нужно, а если это 'какой-нибудь лишний код', то он будет нетривиален. Проблема в том, что шаблон function_traits работает на сигнатурах функций, а не на реальных указателях на функции, так что проблема изменилась с 'get the return type from a function pointer' на 'get the signature from a function pointer', что, наверное, самая сложная часть там.

.
7
ответ дан 5 December 2019 в 08:52
поделиться

Как подсказывают 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);

Это не совсем та форма, к которой я стремился с моим оригинальным вопросом, но она достаточно близка мне.

.
0
ответ дан 5 December 2019 в 08:52
поделиться

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:

  • Это будет работать для функций любой массивности до 10, чего должно быть достаточно для наиболее разумного использования.
  • Это использование BOOST_TYPEOF работает на платформах, которые не поставляют нативный тип, поэтому он достаточно портативен.
5
ответ дан 5 December 2019 в 08:52
поделиться

Попробуйте что-нибудь подобное:

template<class T> struct magic_template
{};

template<class T> struct magic_template<T()>
{
    typedef T type;
};
-1
ответ дан 5 December 2019 в 08:52
поделиться

В C++ 0x используйте decltype.

Для обсуждения проблем и попытки построить решение для более раннего стандарта Си++ смотрите здесь:

Скотт Майерс "бросает вызов" (PDF) и Андрей Александреску пытается решить его

2
ответ дан 5 December 2019 в 08:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: