2015-06-10 4 views
3

Я пишу функцию шаблона, которая получает объект std::function (сгенерировано путем вызова std::bind с соответствующими аргументами). В этой функции я хотел бы определить тип возвращаемого значения этого объекта функции. Возможно ли это?Определение типа возврата std :: function

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

Что-то вроде:

template <typename T> 
T::return_type functionObjWrapper(T functionObject) { 
    // ... 
    return functionObject(); 
} 

Благодарности

+0

'std :: bind' не возвращает' std :: function' – Barry

+0

Нет, но возвращает возвращаемый объект, и этого достаточно для инициализации 'std :: function'. – MSalters

ответ

9

Вы можете сделать это с помощью decltype и замыкающие возвращаемый тип:

template <typename T> 
auto functionObjWrapper(T functionObject) -> decltype(functionObject()) { 
    // ... 
    return functionObject(); 
} 
+0

Совместим только с C++ 14! –

+2

@DavidHaim Работает отлично, когда я использую режим C++ 11 в GCC 4.7.2 (который не имеет режима C++ 14). Кроме того, возвращаемые возвращаемые типы были частью стандарта C++ 11, а также 'decltype'. –

+1

@DavidHaim Это простой старый C++ 11. В C++ 14 вы можете полностью удалить возвращаемый возвращаемый тип. – Barry

2

Вы ищете std::function<F>::result_type

Т.е.

template <typename F> 
typename std::function<F>::result_type 
functionObjWrapper(std::function<F> functionObject) { 
    // ... 
    return functionObject(); 
} 

typename перед тем std::function<F>::result_type необходима, потому что это зависит от имени типа.

0
template <class F> 
std::result_of_t<F&()> functionObjWrapper(F functionObject) { 
    // ... 
    return functionObject(); 
} 

std::result_of принимает выражение типа, которое «выглядит как вызов функции». Затем он сообщает вам, что произойдет, если вы выполнили вызов функции с этим вызываемым типом и этими аргументами.

Если вам не хватает C++ 14, заменить std::result_of_t<?> с typename std::result_of<?>::type, или написать свой собственный:

template<class Sig> 
using result_of_t=typename std::result_of<Sig>::type; 

Во многих реализациях C++ 11, result_of даже SFINAE удобно.

Я делаю F&() вместо F(), потому что мы будем использовать неконсольное lvalue типа F для выполнения вызова. Если ваша последняя строка была std::move(functionObject)() или std::forward<F>(functionObject)(), вы бы сделали result_of_t<F()>.

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