c++ - 为什么 C++ 模板让我绕过不完整的类型(前向声明)?

标签 c++ templates forward-declaration

我尝试了以下简单程序的三个迭代。这是编写一对容器和迭代器类的高度简化的尝试,但我遇到了不完整类型(前向声明)的问题。我发现,一旦我对所有内容进行模板化,这实际上是可能的——但前提是我实际使用了模板参数! (我通过查看 Google sparsetable code 意识到了这一点。)

有任何提示可以解释为什么第二个有效而第三个无效吗? (我知道为什么第一个不起作用——编译器需要知道容器的内存布局。)

提前致谢。

// This doesn't work: invalid use of incomplete type.
#if 0
struct container;
struct iter {
  container &c;
  int *p;
  iter(container &c) : c(c), p(&c.value()) {}
};
struct container {
  int x;
  int &value() { return x; }
  iter begin() { return iter(*this); }
};
int main() {
  container c;
  c.begin();
  return 0;
}
#endif

// This *does* work.
template<typename T> struct container;
template<typename T> struct iter {
  container<T> &c;
  T *p;
  iter(container<T> &c) : c(c), p(&c.value()) {}
};
template<typename T> struct container {
  T x;
  T &value() { return x; }
  iter<T> begin() { return iter<T>(*this); }
};
int main() {
  container<int> c;
  c.begin();
  return 0;
};

// This doesn't work either.
#if 0
template<typename T> struct container;
template<typename T> struct iter {
  container<int> &c;
  int *p;
  iter(container<int> &c) : c(c), p(&c.value()) {}
};
template<typename T> struct container {
  int x;
  int &value() { return x; }
  iter<int> begin() { return iter<int>(*this); }
};
int main() {
  container<int> c;
  c.begin();
  return 0;
}
#endif

最佳答案

第一个需要 container 的定义,因为您正在进行复制操作。如果你在 container 的定义之后定义 iter 的构造函数,你就没问题了。所以:

struct container;
struct iter {
  container &c;
  int *p;
  iter(container &c);
};

struct container {
  int x;
  int &value() { return x; }
  iter begin() { return iter(*this); }
};

iter::iter(container &c) : c(c), p(&c.value()) {}

int main() {
  container c;
  c.begin();
  return 0;
}

第二个示例之所以有效,是因为在您在 main 函数中实际实例化一个类之前,没有类。到那时所有类型都已定义。尝试在 main 之后移动任何 itercontainer 模板定义,您将遇到错误。

第三个例子是 int 的特化,或者看起来是这样。这应该可以编译,因为未使用 iter 的模板参数。您的特化语法有点偏离。但是,没有合适的构造函数,因此您只会得到 x 的垃圾。此外,迭代器可以通过指针很好地建模。传递 this 的值不会有太大帮助。序列而不是单个对象通常需要迭代器。不过,没有什么可以阻止您构建一个。

并且您不需要在函数体之后添加 ;

关于c++ - 为什么 C++ 模板让我绕过不完整的类型(前向声明)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/620378/

相关文章:

C++ 在一个文件中定义类并在另一个文件中转发声明它

c++ - 前向声明类模板的成员枚举

c++ - 创建对象并将其插入 vector 的正确方法是什么?

c++ - 如何使用 CMake 在 MinGW 上激活 c++11 支持?

c++ - 与 std::unique_ptr 关联的错误

c++ - 是否有可能在 C++ 中使用 std::atomic_flag 获得线程锁定机制?

c++ - 对不同类型使用具有不同返回值的模板函数不起作用

c++ - 为什么概念 c++ 中没有前向声明?

c++ - 如何为模板化类型提供 void* 访问器?

c++ - 为什么我的 C++ 编译器不能推导出 boost 函数的模板参数?