为什么typedef会影响函数重载?

时间:2011-09-14 23:11:53

标签: c++ visual-studio-2008 templates typedef

我在课堂上有两个功能(请评论问题,而不是编码风格):

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是一个char)转换为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呢?为什么要编译而另一个不编译?


编辑:在测试了Oli的代码之后,我检查了它,我忘了将const添加到SEGMENT#2中的迭代器中。除了在这种情况下添加const没有意义的论点之外,为什么会产生T*而不是iterator的错误。如果你想尝试一下,这里是Oli的代码稍作修改:

#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 个答案:

答案 0 :(得分:5)

以下代码compiles fine

#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 :(得分:1)

它会产生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
}