In general, this unpleasant problem with templates should require duplication, because the semantics, where the variable is const or not, or the link or not, are quite different.
The C ++ 11 solution is a "decltype", but it is a bad idea because all it does is a complex and already broken type system.
Regardless of what the Standard or the Committee says, "const int" is and never will be a type. Nor will "int &" ever be a type. Therefore, the type parameter in the template should never be associated with such non-types, and, fortunately, for deduction this is so. Unfortunately, you can still explicitly force this unprincipled lookup.
There are some idiotic rules that try to "fix" this problem, for example, "const const int", decreasing to "const int", I'm not even sure what will happen if you get "int and &": remember, even the Standard is not considered "int &". as a type, there is a type "int lvalue", but which is different:
int x; // type is lvalue int int &y = x; // type is lvalue int
The correct solution to this problem is actually quite simple: everything is a mutable object. Throw away "const" (this is not so useful) and throw away links, lvalues ββand rvalues. It is obvious that all types of classes are addressed, rvalue or not (the pointer to "this" is the address). The committee directed a vain attempt to prohibit the appointment and appeal of rvalues. The addressing case works, but it's easy to get away with a trivial cast. The assignment case does not work at all (since assignment is a member function, and r values ββare not constants, you can always assign the class typed by rvalue).
In any case, the crowd of template metaprograms has "decltype", and with this you can find the encoding of the declaration, including any "const" and "&". bit, and then you can decompose this encoding using various library operators. This cannot be done before, because this information is not typical information ("ref" is actually memory allocation information).