C++ template specialization: unexpected function overload lookup result
c++, specialization, template-specialization, templates
Solution
The `TT&&` in `Inst(TT &&) {out(3);}` is somewhat special. So, special that there is even a special "term" coined for them called `universal reference`.
In short `TT&&` is not what you think it is. There are two things that come into play here: Reference Collapsing and Template Deduction
Since `TT` is a template parameter and you stuck `&&` in front of it, this is what `T&&` becomes in your example:
Inst<K> I1{k}; ---> Inst(K&)
Inst<K> I2{kk}; ---> Inst(KK&)
Inst<K> I3{i}; ---> Inst(Inst<K>&)
Inst<K> I4{K()}; ---> Inst(K&&)
Inst<K> I5{KK()} ---> Inst(KK&&)
What happens is `TT&&` becomes an exact match and is the selected constructor for all the calls you make, which is why you see `3` for each one (except for `i` and `I6`).
For further reading, please see:
Universal References and the Copy Constructor.
Advantages of using forward.
Problem
While trying to write a wrapper for `shared_ptr` that would hide allocation and deallocation of memory from user while supporting inheriting classes, I have stumbled upon very weird errors suggesting that either compiler looks up wrong functions during an overload, or my knowledge regarding mixing overloads and templates is wrong. So I wrote this thing for testing: ``` #include <iostream> void out(int i) { std::cout << i << '\n'; } template <class T> struct Inst { template <class TT> Inst(const TT &) {out(1);} Inst(const Inst &) {out(2);} template <class TT> Inst(TT &&) {out(3);} Inst(Inst &&) {out(4);} Inst() {out(-1);} ~Inst() {out(1000);} }; class K {}; class KK : K {}; int main() { out(3000); K k; KK kk; Inst<K> i; Inst<K> I1{k}; Inst<K> I2{kk}; Inst<K> I3{i}; Inst<K> I4{K()}; Inst<K> I5{KK()}; Inst<K> I6{Inst<K>()}; out(2000); } ``` What I would reasonably expect would be `I1` and `I2` writing `1`, `I3` writing `2`, `I4` and `I5` writing `3` and `I6` writing `4`, and at least two other objects writing `-1` at various points. When compiled with gcc 4.8.2 using `-std=c++11`, however, my machine skipped one of objects, and wrote `3` for every other non-automatic constructor called. What am I doing wrong?