在C++(STL)中,我们定义了const和非const方法以及两种用于迭代集合的迭代器:
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)
怎么了?
解决方案是使您的范围存在于容器外部,但仍然引用它.如果范围在容器内,则它受传递const规则的约束,但如果它在外面,则可以在可变范围内保留const引用.如果在同一文件中定义它们,则范围仍然可以看到容器的私有成员.
注意:
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);
}
}