Card 1 / 7
Three function templates differ only in how the parameter binds, and each is called once with the same const object:
template <class T> void by_value(T param);
template <class T> void by_ref(T& param);
template <class T> void by_cref(const T& param);
const int answer = 42;
by_value(answer);
by_ref(answer);
by_cref(answer);What does T deduce to in each of the three calls?
by_value: int · by_ref: const int · by_cref: intCorrect answerCorrect. A by-value parameter is a fresh copy, so top-level const (and reference-ness) is dropped: T = int. In T& the parameter type itself carries no const, so the argument's const has nowhere to go but into T: T = const int. In const T& the parameter already supplies the const, so T is just int.
int in all three — a parameter's own const is never part of T.Incorrect for by_ref. Nothing in void by_ref(T&) can carry the argument's const except T itself, so T = const int and the parameter is const int&. If T were plain int, the call would bind an int& to a const int object — a hole in the type system.
const int in all three — the argument is const, so T picks that up.Incorrect for by_value and by_cref. A by-value parameter copies, and you may freely modify your own copy, so top-level const is stripped: T = int. And in const T& the const is already written in the parameter, so folding it into T as well would give the redundant const const int&; T = int.
by_value: int · by_ref: int · by_cref: const intIncorrect — the last two are swapped. T& has no const of its own, so it absorbs the argument's: T = const int. const T& supplies the const in the parameter, so T stays int. The by-value answer is right: a copy drops top-level const.
Card 2 / 7
take declares its parameter as T&& where T is deduced from the call. That combination is a forwarding reference, and it deduces differently from a plain rvalue reference such as void take(int&&).