迭代 D 中的 const 集合
Iteration over const collections in D
在 C++ (STL) 中,我们定义了常量和非常量方法以及两种用于迭代集合的迭代器:
class Container
{
public:
iterator begin();
const_iterator begin() const;
};
我们如何将此技术扩展到 D?我的第一次尝试:
class Container(T) {
class Range {
ref T front();
// implementation
}
class ConstRange {
T front() const;
// implementation
}
Range all() {
return new Range(/**/);
}
ConstRange all() const {
return new ConstRange(/**/);
}
}
unittest {
alias list = List!int;
const list L = new list;
writeln(L.all());
}
但是失败了。我有一个错误:
Error: nested type List.List!int.List.Range should have the same or weaker constancy as enclosing type const(List!int)
怎么了?
解决办法是让你的范围存在于容器之外,但仍然引用它。如果范围在容器内,则它受传递常量规则的约束,但如果在容器外,则可以在可变范围内保留常量引用。如果将它们定义在同一个文件中,范围仍然可以看到容器的私有成员。
观察:
class Container(T) {
private T[] contents;
this(T[] contents) {
this.contents = contents;
}
RangeOver!(Container!T, T) getRange() {
return RangeOver!(Container!T, T)(this);
}
RangeOver!(const(Container!T), const(T)) getRange() const {
return RangeOver!(const(Container!T), const(T))(this);
}
}
struct RangeOver(Container, T) {
Container container;
size_t iterationPosition;
this(Container container) {
this.container = container;
this.iterationPosition = 0;
}
ref T front() {
return container.contents[iterationPosition];
}
bool empty() {
return iterationPosition == container.contents.length;
}
void popFront() {
iterationPosition++;
}
}
void main() {
import std.stdio;
// mutable iteration
{
writeln("about to mutate...");
auto container = new Container!int([1,2,3]);
foreach(ref item; container.getRange()) {
writeln(item);
item += 5;
}
writeln("mutation done");
// changes seen
foreach(item; container.getRange())
writeln(item);
}
// const iteration
{
writeln("consting it up y0");
const container = new Container!int([1,2,3]);
// allowed
foreach(item; container.getRange())
writeln(item);
}
}
在 C++ (STL) 中,我们定义了常量和非常量方法以及两种用于迭代集合的迭代器:
class Container
{
public:
iterator begin();
const_iterator begin() const;
};
我们如何将此技术扩展到 D?我的第一次尝试:
class Container(T) {
class Range {
ref T front();
// implementation
}
class ConstRange {
T front() const;
// implementation
}
Range all() {
return new Range(/**/);
}
ConstRange all() const {
return new ConstRange(/**/);
}
}
unittest {
alias list = List!int;
const list L = new list;
writeln(L.all());
}
但是失败了。我有一个错误:
Error: nested type List.List!int.List.Range should have the same or weaker constancy as enclosing type const(List!int)
怎么了?
解决办法是让你的范围存在于容器之外,但仍然引用它。如果范围在容器内,则它受传递常量规则的约束,但如果在容器外,则可以在可变范围内保留常量引用。如果将它们定义在同一个文件中,范围仍然可以看到容器的私有成员。
观察:
class Container(T) {
private T[] contents;
this(T[] contents) {
this.contents = contents;
}
RangeOver!(Container!T, T) getRange() {
return RangeOver!(Container!T, T)(this);
}
RangeOver!(const(Container!T), const(T)) getRange() const {
return RangeOver!(const(Container!T), const(T))(this);
}
}
struct RangeOver(Container, T) {
Container container;
size_t iterationPosition;
this(Container container) {
this.container = container;
this.iterationPosition = 0;
}
ref T front() {
return container.contents[iterationPosition];
}
bool empty() {
return iterationPosition == container.contents.length;
}
void popFront() {
iterationPosition++;
}
}
void main() {
import std.stdio;
// mutable iteration
{
writeln("about to mutate...");
auto container = new Container!int([1,2,3]);
foreach(ref item; container.getRange()) {
writeln(item);
item += 5;
}
writeln("mutation done");
// changes seen
foreach(item; container.getRange())
writeln(item);
}
// const iteration
{
writeln("consting it up y0");
const container = new Container!int([1,2,3]);
// allowed
foreach(item; container.getRange())
writeln(item);
}
}