Следующий небольшой пример показывает мою проблему:
template<class T> struct X
{
static void xxx(T& x) { }
static void xxx(T&& x) { }
};
int main(int argc, char** argv)
{
int x = 9;
X<int>::xxx(x); // OK.
X<int&>::xxx(x); // ERROR!
return 0;
}
Сообщение об ошибке (GCC):
ошибка: «static void X :: xxx (T &&) [with T = int &]» не может быть перегружен
ошибка: с «static void X :: xxx (T &) [with T = int &]»
Почему? T = int&
---> T&
заменяется на int&&
в static void xxx(T& x)
?
Если ответ на вопрос положительный, то:
T&
не является lvalue-ссылкой, а становится rvalue-ссылкой!- И следующий код должен работать:
Но этого не произошло:
template<class T> struct X
{
static void xxx(T& x) { }
};
int main(int argc, char** argv)
{
X<int&>::xxx(2); // ERROR!
return 0;
}
Сообщение об ошибке (GCC):
ошибка: нет соответствующей функции для вызова «X :: xxx (int)»
примечание: кандидатами являются: static void X :: xxx (T &) [with T = int &]
Тогда T&
с T = int&
не равно T&&
и не является rvalue-ссылкой. но если это не так, почему первый пример не работает? (это рекурсивная проблема!)
Но подобной проблемы не возникало для типов указателей:
#include <iostream>
template<class T> struct X
{
static void xxx(T* x) { std::cout << **x << std::endl; }
};
int main(int argc, char** argv)
{
int x = 10;
int* xx = &x;
X<int*>::xxx(&xx); // OK. call X<int*>::xxx(int**)
return 0;
}
Почему ссылки различаются таким поведением?