I was reading Chapter 25 from C++ Templates - The Complete Guide - 2nd ed., where, given code more or less like this
#include <utility>
template<typename...>
struct Tuple;
template<typename H, typename ...T>
struct Tuple<H, T...> {
H h;
Tuple<T...> t;
Tuple() {}
template<typename HH, typename ...TT>
Tuple(HH&& h, TT&& ...t)
: h{std::forward<HH>(h)}
, t{std::forward<TT>(t)...} {}
template<typename HH, typename ...TT>
Tuple(Tuple<HH, TT...> const& other)
: h{other.h}
, t{other.t} {}
};
template<>
struct Tuple<> {};
and a t
defined like this
Tuple<int, double, std::string> const t;
the following definition fails
Tuple<long int, long double, std::string> t2{t};
Ok, good, I knew why that was happening and I started writing a margin note:
The reason is that
t
is notconst
, which means thattemplate<typename HH, typename ...TT> Tuple(HH&&, TT&& ...)
is a perfect match for the call, whereastemplate<typename HH, typename ...TT> Tuple(Tuple<HH, TT...> const&)
requies thatconst
is added to the argument to match the parameter.
And I've verified it: if I make t
const
, then the definition of t2
is fine an calls the correct ctor.
But then (assuming I don't add the const
as per previous paragraph) I wondered "What type of match is the second, if the first is perfect?"
I was in double as to which of the several non-perfect matches that would be, so I moved forward to Appendix C, pages 682-683, Section C.2 to find out:
- Perfect match. The parameter has the type of the expression, or it has a type that is a reference to the type of the expression (possibly with added
const
and/orvolatile
qualifiers).- Match with minor adjustments. This includes, for example, the dacy of an array variable to a pointer to its first element or the addition of
const
to match an argument of typeint**
to a parameter of typeint const* const*
And now I'm a bit puzzled, because the ctor template<typename HH, typename ...TT> Tuple(Tuple<HH, TT...> const& other)
, with reference to the definition of t2
, has a parameter with type a reference to the type of the expression initializing it, because of template type deduction, with just an added cosnt
. So isn't this exactly what a perfect match is, based on the excerpt from the book? Or am I misreading the book? Or my own code?