Ответ 1
Удалить ссылку:
template<typename T>
void Test(const typename std::remove_reference<T>::type & param)
{
param = 20;
}
Теперь он работает так, как ожидалось.
В шаблоне С++ с общим типом T я могу использовать
const T &
чтобы получить ссылку на константу T. Однако если теперь T сам является ссылочным типом (например, T = int &), вышеуказанный термин разрешает
int &
а не
const int &
что вполне имеет смысл, поскольку любая ссылка сама по себе всегда постоянна. Тем не менее, есть ли еще способ потребовать
const T &
если сам T является ссылочным типом?
Изменить: пример кода для оценки (компилятор g++):
template <typename T> class TemplateClass
{
public:
void foo(const T &bar) { }
};
int main()
{
TemplateClass<int &> x;
x.foo(0); // <-- compile error: no conversion from int to int&
return 0;
}
Удалить ссылку:
template<typename T>
void Test(const typename std::remove_reference<T>::type & param)
{
param = 20;
}
Теперь он работает так, как ожидалось.
Вы всегда можете использовать специализированную специализацию для реализации другой версии для любого типа ссылок:
template <typename T> struct X {
void foo(T const&);
};
template <typename T> struct X<T&> {
void foo(T const&);
};
Теперь X<int>::foo
ожидает, что int const&
и X<int&>::foo
тоже ожидают int const&
.
Однако из вашего вопроса не совсем ясно, что вы пытаетесь сделать точно.
Изменить: моя версия g++ (4.6.1) не жалуется без специализации шаблонов для следующих
int i = 7;
X<int&>(i);
Пока он делает для
X<int&>(7);
Какая правильная IMO, потому что вы пытаетесь преобразовать временную (7
) в изменяемую ссылку (даже если это ссылка на константную ссылку).
Редактирование 2: Если вы хотите уменьшить дубликат кода, то не специализируйте свой исходный класс, но используйте это:
template <typename T> struct R {
typedef T& Ref;
typedef T const& ConstRef;
};
template <typename T> struct R<T&> {
typedef T& Ref;
typedef T const& ConstRef;
};
template<typename T> struct X {
void foo(typename R<T>::ConstRef x);
};
Я столкнулся с той же проблемой. Кажется, что '&' оператор преобразования типа привязывается сильнее, чем определитель 'const'. Итак, когда у нас есть этот код:
template<class t>
void fun(const t i)
{
}
fun<int&>();
функция заканчивается типом void (int &), а не ожидаемым void (const int &).
Чтобы решить эту проблему, я определил этот шаблон:
template<class t> struct constify { typedef t type; };
template<class t> struct constify<t&> { typedef const t& type; };
Теперь определите свою функцию как:
template<class t>
void fun(typename constify<t>::type i)
{
}
fun<int&>();
При необходимости созданная функция будет иметь тип void (const int &).