Есть ли declval для указателей функций?

У меня есть функция, и мне нужно проверить, могу ли я передать ей аргумент заданного типа. Например:

template<typename T, auto F>
decltype(F(declval<T>{})) foo();

призвание foo<int, bar>() делает 2 вещи:

  1. Устанавливает тип возврата foo будет иметь тот же тип возврата, что и bar
  2. Гарантирует, что 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. Я бы посоветовал имитировать их, чтобы получить наиболее плавное обновление.

Другие вопросы по тегам