Почему typedef влияет на перегрузки функций? - PullRequest
3 голосов
/ 15 сентября 2011

У меня есть две функции в классе (пожалуйста, прокомментируйте проблему, а не стиль кодирования):

template <typename T>
class myStringClass
{
public:
  ...

  typedef T* iterator;

  void erase(size_t pos, size_t n); // FUNC#1
  void erase(iterator first, iterator last); //FUNC#2
};

FUNC#2 стирает диапазон, а FUNC#1 просто вызывает FUNC#2 после расчета соответствующего диапазона. В FUNC#1 вместо объявления iterator для вычисления диапазона я объявил T*, что (должно быть?) По сути то же самое.

// SEGMENT#1 in function erase(size_t pos, size_t n)
T* begin = m_begin + pos;
T* end = begin + n;
erase(begin, end); // call FUNC#2

Однако, это не компилируется. Компилятор жалуется, что он не может преобразовать T * (где T - символ) в size_t (то есть пытается вызвать `FUNC # 1). Но если я изменю приведенный выше код на:

// SEGMENT#2 in function erase(size_t pos, size_t n)
iterator begin = m_begin + pos;
iterator end = begin + n;
erase(begin, end); // call FUNC#2

Тогда компилятор счастлив. Я предположил, что typedef был псевдонимом и не проверялся типом. Итак, SEGMENT#1 == SEGMENT#1, что касается компилятора? Почему один компилируется, а другой нет?


РЕДАКТИРОВАТЬ: После тестирования кода Оли я проверил его на свой, и я забыл добавить const к итераторам в SEGMENT#2. Помимо аргумента, что добавление const не имеет смысла в этом случае, почему это вызывает ошибку для T*, а не iterator. Вот немного измененный код Оли, если вы хотите попробовать:

#include <stdlib.h>

template <typename T>
class myStringClass
{
private:
  T *m_begin;

public:

  typedef T* iterator;

  void erase(size_t pos, size_t n); // FUNC#1
  void erase(iterator first, iterator last); //FUNC#2
};


template <typename T>
void myStringClass<T>::erase(size_t pos, size_t n)
{
  const T* begin = m_begin + pos; // replace with iterator to compile
  const T* end = begin + n; // replace with iterator to compile
  erase(begin, end); // call the overload
}


template <typename T>
void myStringClass<T>::erase(const iterator first, const iterator last)
{
}

int main(void)
{
  myStringClass<char> x;
  x.erase(1,1);
}

Ответы [ 2 ]

5 голосов
/ 15 сентября 2011

Следующий код прекрасно компилируется :

#include <stdlib.h>

template <typename T>
class myStringClass
{
private:
  T *m_begin;

public:

  typedef T* iterator;

  void erase(size_t pos, size_t n); // FUNC#1
  void erase(iterator first, iterator last); //FUNC#2
};


template <typename T>
void myStringClass<T>::erase(size_t pos, size_t n)
{
    T* begin = m_begin + pos;
    T* end = begin + n;
    erase(begin, end); // call the overload
}


template <typename T>
void myStringClass<T>::erase(iterator first, iterator last)
{
}


int main(void)
{
    myStringClass<char> x;
    x.erase(1,1);
}

Ваша проблема должна быть в другом месте.

ОБНОВЛЕНИЕ

СейчасВы показали свой реальный код ...

Проблема в том, что вы пытаетесь вызвать функцию, которая принимает не const указатели, передавая ей const указатели.Это недействительно.

ОБНОВЛЕНИЕ 2

Теперь, когда вы показали свой "настоящий реальный" код ...

Проблема в том,что это:

typedef T *U;
const U x;

- это не то же самое, что:

const T *x;

, на самом деле это то же самое, что:

T *const x;
1 голос
/ 15 сентября 2011

Выдает ошибку для const T *, а не для const iterator.И причина в том, что const iterator увеличивается до T * const, а не const T *.

extern int foo(int i);
extern int bar(int *i);

void baz()
{
   const int x = 5;
   int y = x;
   foo(x); // Perfectly fine
   foo(y); // Also perfectly fine
   bar(&x); // Not fine at all.
   bar(&y); // Perfectly fine.
}

void bouncy()
{
   typedef int my_t;
   typedef int *myptr_t;
   typedef const my_t const_my_t; // const (int) aka const int
   typedef const myptr_t const_myptr_t; // const (int *) aka int * const
}
...