2016-12-31 2 views
9

У меня есть функция, где называется x, которая возвращает значение ноу и познавший параметры:Как получить возвращаемый тип функции для использования в шаблоне?

int x(int y); 

У меня есть где-то еще, я хочу, чтобы создать контейнер, чтобы содержать n вызов этой функции. Затем я хочу выполнить это много раз.

Проблема в том, что я не хочу полагаться на то, что это возвращаемый тип int. Мне нужно вывести возвращаемый тип во время компиляции. Что-то вроде:

std::vector<result_of<x(int)>::type> results; 

Но я не хочу указывать значения параметров, потому что они статичны.

+0

[Этот вопрос в StackOverflow] (http://stackoverflow.com/questions/11310898/how-do-i-get-the-type-of-a-variable) может ответить на ваш вопрос. – Nietvoordekat

+0

Вы можете взглянуть на решение здесь: http://stackoverflow.com/a/41301717/2378300 – Jonas

ответ

6

Вы можете создавать свои собственные черты, что-то вроде:

template <typename F> struct my_result_of; 

template <typename F> struct my_result_of<F*> : my_result_of<F> {}; 

template <typename Ret, typename ... Ts> 
struct my_result_of<Ret(Ts...)> 
{ 
    using type = Ret; 
}; 

template <typename F> using my_result_of_t = typename my_result_of<F>::type; 

И использовать его как (предполагая отсутствие перегрузки x):

std::vector<my_result_of_t<decltype(x)>::type> results; 
5

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

std::vector<decltype(x(std::declval<T>()))> results; 
+1

[Это не работает.] (Http://coliru.stacked-crooked.com/a/755fc639873ce270). вы проверяете свое решение? – cpplearner

+1

@cpplearner: ваша точка. Это не так, как result_of работает. Изменено на 'decltype'. – erenon

+0

"аргумент шаблона функции вызывающего абонента"? Функция, желающая вызвать 'x', не имеет аргумента шаблона. – NeomerArcana

2

Вы можете злоупотреблять std::function::result_type:

int x(int y); 
static_assert(std::is_same_v<int,std::function<decltype(x)>::result_type>); 

Конечно, это будет работать только если x действительно функция. Если x - произвольный функциональный объект, то его тип результата может зависеть от его типа аргумента, и в этом случае вы не можете узнать его тип результата без указания аргументов.

2

Я предполагаю, что вы можете использовать до самого последнего стандартная версия, поскольку вы не указали ее.
Вот минимальный, рабочий пример:

#include<vector> 
#include<functional> 
#include<utility> 

template<std::size_t... I, typename F, typename... A> 
auto gen(std::index_sequence<I...>, F &&f, A... args) { 
    return std::vector<decltype(std::forward<F>(f)(args...))>{ 
     (I, std::forward<F>(f)(args...))... 
    }; 
} 

template<std::size_t N, typename F, typename... A> 
auto gen(F &&f, A... args) { 
    return gen(std::make_index_sequence<N>{}, std::forward<F>(f), args...); 
} 

int f(int, char) { return 0; } 

int main() { 
    auto vec = gen<10>(&f, 0, 'c'); 
} 

Возврат тип вашей функции легко выводится:

decltype(std::forward<F>(f)(args...)) 

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

Для этого я использовал std::index_sequence для создания пакета параметров, имеющего нужный размер.
Затем сам вектор инициализации, как это следующим образом:

(I, std::forward<F>(f)(args...))... 

Основная идея заключается в том, чтобы использовать оператор запятой, чтобы распаковать пакет параметров, упомянутых выше, и выполнять N раз функцию. Значения, возвращаемые вызовами f, используются для заполнения вектора.

Отметьте, что args не переадресованы на f.
Это может вызвать проблемы в случае перемещения предметов, потребляемых во время первого выполнения.

Смежные вопросы