Есть ли declval для указателей функций?
У меня есть функция, и мне нужно проверить, могу ли я передать ей аргумент заданного типа. Например:
template<typename T, auto F>
decltype(F(declval<T>{})) foo();
призвание foo<int, bar>()
делает 2 вещи:
- Устанавливает тип возврата
foo
будет иметь тот же тип возврата, что иbar
- Гарантирует, что
bar
это функция, которая принимает аргумент типаT
К сожалению, у меня нет доступа к auto
типы шаблонов, но я все еще хочу выполнить оба этих. Что мне нужно это decltype
для указателей на функции, которые позволили бы мне сделать что-то вроде этого:
template <typename T, typename F>
decltype(declval<F>(declval<T>{})) foo();
Так что я все еще могу позвонить foo<int, bar>()
и получить тот же результат. Конечно нет declval
для указателей функций. Но есть ли другой способ сделать это?
1 ответ
Конечно, для указателей на функции не существует declval.
Что вы имеете в виду? std::declval
отлично работает с типами указателей на функции:
template<typename F, typename... Args>
using call_t = decltype(std::declval<F>()(std::declval<Args>()...));
В этом примере F
может быть указателем на тип функции, лямбда-типом или любыми вызываемыми типами.
Вот пример использования:
template<typename T, typename F>
auto foo() -> call_t<F, T>;
Другой пример, использующий идиому обнаружения (реализуемо в C++11):
template<typename F, typename... Args>
using is_callable = is_detected<call_t, F, Args...>;
static_assert(is_callable<void(*)(int), int>::value, "callable")
Обратите внимание, что все это можно заменить на std::invoke_result_t
а также std::is_invocable
в C++17. Я бы посоветовал имитировать их, чтобы получить наиболее плавное обновление.