Card 1 / 7
SFINAE — substitution failure is not an error — has a boundary, and it is exactly the boundary an interviewer probes. Both templates below make the same mistake about T = int; only one of them is survivable.
template <class T> typename T::type in_signature(const T&); // A
std::string in_signature(...);
template <class T> std::string in_body(const T& v) { // B
typename T::type local{};
return "template";
}
std::string in_body(...);
in_signature(42);
in_body(42);What happens at each of the two calls?
... fallback; B fails to compile.Correct answerCorrect. typename T::type in A is written in the return type, part of the signature — the immediate context of substitution — so the failure just removes that candidate. In B the same expression is in the body: the template wins overload resolution first, and only then is the body instantiated, where an invalid expression is an ordinary error with no candidate left to fall back to.
T.Incorrect, and it is the most expensive misunderstanding here. SFINAE only applies while the compiler is deciding whether a candidate is viable, which is finished before any body is compiled. A body error arrives too late to change the choice.
int has no member type either way.Incorrect for A. That is the entire point of the rule: a substitution failure in the immediate context is not an error, it is a quiet "this candidate does not apply". Without it, every enable_if and every detection trait would be a compile error instead of a decision.
Incorrect. A discarded candidate is never instantiated, so there is no code to emit and nothing to link. The call in A resolves to the fallback at compile time, exactly as if the template had not been declared.
Card 2 / 7
describe currently accepts every type, so a double is wrongly reported as "integral". Constrain it with std::enable_if_t so that only integral types are even considered, and everything else reaches the ... catch-all already in…