Подтвердить что ты не робот

Ссылки const в шаблонах С++

В шаблоне С++ с общим типом 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;
}
4b9b3361

Ответ 1

Удалить ссылку:

template<typename T>
void Test(const typename std::remove_reference<T>::type & param)
{
        param = 20;
}

Теперь он работает так, как ожидалось.

Ответ 2

Вы всегда можете использовать специализированную специализацию для реализации другой версии для любого типа ссылок:

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);
};

Ответ 3

Я столкнулся с той же проблемой. Кажется, что '&' оператор преобразования типа привязывается сильнее, чем определитель '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 &).