Я хотел бы создать функцию типа компиляции, которая, учитывая любой вызываемый объект f
(функция, лямбда-выражение, функциональный объект,...) и тип T
, оценивается как true, если f
может быть вызван с аргументом типа T
, а false, если он не может.
Пример:
void f1(int) { ... }
void f2(const std::string&) { ... }
assert( is_callable_with<int>(f1));
assert(!is_callable_with<int>(f2));
Я думаю, что разумное использование правила SFINAE могло бы достичь этого. Возможно, так или иначе:
template<typename T, typename F>
constexpr bool is_callable_with(F&&, typename std::result_of<F(T)>::type* = nullptr) {
return true;
}
template<typename T, typename F>
constexpr bool is_callable_with(F&&) {
return false;
}
Но это не сработает, потому что если f
можно вызывать с помощью T
, обе перегрузки участвуют в разрешении перегрузки, и есть двусмысленность. Я бы хотел переписать его, так что в положительном случае первая перегрузка будет выбрана с помощью разрешения перегрузки над вторым. Не уверен, что я даже на правильном пути здесь.