Если вам нужен тип чего-то, что не похоже на вызов функции, std::result_of
просто не применяется. decltype()
может дать вам тип любого выражения.
Если мы ограничимся только разными способами определения типа возврата вызова функции (между std::result_of_t<F(Args...)>
и decltype(std::declval<F>()(std::declval<Args>()...)
), то есть разница.
std::result_of<F(Args...)
определяется как:
Если выражение
INVOKE (declval<Fn>(), declval<ArgTypes>()...)
хорошо
образуется, когда рассматривается как
неоцененный операнд (пункт 5),
член typedef тип должен назвать
тип decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...));
в противном случае не должно быть члена
тип.
Разница между result_of<F(Args..)>::type
и decltype(std::declval<F>()(std::declval<Args>()...)
заключается именно в этом INVOKE
. Использование declval
/ decltype
напрямую, в дополнение к тому, что он немного дольше печатается, допустимо только в том случае, если F
напрямую вызывается (тип объекта функции или функция или указатель на функцию). result_of
дополнительно поддерживает указатели на функции-члены и указатели на данные-члены.
Первоначально, использование declval
/ decltype
гарантировало дружественное к SFINAE выражение, тогда как std::result_of
может привести к серьезной ошибке вместо ошибки вывода. Это было исправлено в C ++ 14: std::result_of
теперь требуется для SFINAE (благодаря этой статье ).
Так что на соответствующем компиляторе C ++ 14 std::result_of_t<F(Args...)>
строго превосходит. Он четче, короче и правильно & dagger; поддерживает больше F
s & Dagger; .
<ч />
& dagger; Если вы не используете его в контексте, в котором вы не хотите разрешать указатели для членов, то std::result_of_t
будет успешным в случае, если вы захотите, чтобы он потерпел неудачу.
& Dagger; С исключениями. Хотя он поддерживает указатели на члены, result_of
не будет работать, если вы попытаетесь создать недействительный type-id . Они будут включать функцию, возвращающую функцию или принимающую абстрактные типы по значению. Ex.:
template <class F, class R = result_of_t<F()>>
R call(F& f) { return f(); }
int answer() { return 42; }
call(answer); // nope
Правильное использование было бы result_of_t<F&()>
, но эту деталь вам не нужно помнить с decltype
.