是什么导致了模板和继承的这个莫名其妙的编译器错误?

What is causing this baffling compiler error with templates and inheritance?

花了很长时间才将其提炼到可管理的大小,但这是代码:

template<typename T = uint8_t> struct ArrayRef {
  T* data;
  size_t size;
  size_t capacity;

  ArrayRef<T>(T* d, size_t c, size_t size) : data(d), size(size), capacity(c) {}

  void Add(T* buffer, size_t size) { }
};

struct ByteArray : ArrayRef<uint8_t> {
  ByteArray(uint8_t* d, size_t c, size_t size) : ArrayRef<uint8_t>(d,c,size) {}

  // If this function is removed, the test code can find the inherited Add function
  template <typename T> void Add(T& item) { }
};

void Test() {
  uint8_t ibuf[20];
  ByteArray ba(ibuf, 20, 0);
  uint8_t buf[5];
  ba.Add(buf, sizeof(buf));

如果此代码按原样编译 (g++),我会收到编译器错误:

error: no matching function for call to 'ByteArray::Add(uint8_t [5], unsigned int)

但是,如代码中所述,删除一个函数后,代码编译正常,并且正确找到基 class 中的 Add 函数。这到底是怎么回事?

当名字Add在classByteArray的范围内找到时,名字查找停止,classArrayRef<uint8_t>的范围不会被检查。

你可以将ArrayRef<uint8_t>::Add引入到ByteArray的范围内,就可以被发现并参与重载决议

struct ByteArray : ArrayRef<uint8_t> {
  ByteArray(uint8_t* d, size_t c, size_t size) : ArrayRef<uint8_t>(d,c,size) {}

  // If this function is removed, the test code can find the inherited Add function
  template <typename T> void Add(T& item) { }

  using ArrayRef<uint8_t>::Add;
};