我尝试了以下简单程序的三次迭代。这是编写容器和迭代器对类的高度简化的尝试,但我遇到了不完整类型(前向声明)的问题。我发现,一旦我模仿了一切,这实际上是可能的 - 但只有当我实际使用模板参数时! (我通过查看 Google sparsetable代码。)

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

提前致谢。

// 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之后移动任何 iter 容器模板定义,然后您将遇到错误。

第三个例子是 int 的特化,所以它出现了。这应该编译,因为没有使用 iter 的模板参数。你的专业化语法有点偏。但是,没有适当的构造函数,因此您只会为 x 获取垃圾。此外,迭代器通过指针很好地建模。传递这个的值不会有太大帮助。迭代器通常是序列所必需的,而不是单个对象。但是,没有什么可以阻止你建立一个。

在函数体之后你不需要;

其他提示

你可以在没有模板的情况下通过在容器定义之后定义iter :: 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;
}

模板版本有效,因为在实例化模板时,两个类都是完全定义的。

在第一种情况下,您尝试在定义类之前访问Container类的成员函数,因此这将不起作用。

在第二种情况下,模板在第一次与特定类型一起使用时被实例化。此时,已经在main中定义了Container类,因此它进行了编译。

在第三种情况下,有一个循环引用。容器使用iter而iter使用容器,因此它无法工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top