Predicado en tiempo de compilación de C ++ para probar si un objeto invocable de tipo F se puede llamar con un argumento de tipo T

Me gustaría crear una función de tipo compilación que, dado cualquier objeto invocablef (función, expresión lambda, objeto de función, ...) y un tipoT, se evalúa como verdadero, sif se puede llamar con un argumento de tipoT, y falso si no puede.

Ejemplo:

void f1(int) { ... }
void f2(const std::string&) { ... }

assert( is_callable_with<int>(f1));
assert(!is_callable_with<int>(f2));

Estoy pensando que un uso inteligente de la regla SFINAE podría lograr esto. Posiblemente de alguna manera así:

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;
}

Pero esto no funciona, porque siF es invocable conT, ambas sobrecargas participan en la resolución de sobrecarga y existe una ambigüedad. Me gustaría reescribirlo para que, en el caso positivo, la primera sobrecarga sea seleccionada por la resolución de sobrecarga sobre la segunda. Sin embargo, no estoy seguro de si estoy en el camino correcto aquí.

Respuestas a la pregunta(3)

Su respuesta a la pregunta