I'm trying to implement a variant of buildPath
that is performant (minimal heap-activity) and @safe
and pure
.
My try so far is
/** Returns: Path to $(D this) File. */
string path() @property @safe const pure {
const Dir[] parents;
// collect parenting Dirs
auto currParent = parent;
size_t pathLength = 0; // returned path length
while (currParent !is null) {
if (currParent !is parent) {
pathLength += 1;
}
pathLength += currParent.name.length;
parents ~= currParent;
currParent = parent.parent;
}
// build path
auto path_ = new char[pathLength];
size_t i = 0;
foreach (currParent_; parents) {
const parentName = currParent_.name;
if (i != 0) {
path_[++i] = '/';
}
path_[i .. parentName.length] = parentName[];
i += parentName.length;
}
return path;
}
But it doesn't compile because of problems with constness on parents
and currParent
.
/home/per/Work/justd/fs.d(408): Error: cannot modify const expression parents
/home/per/Work/justd/fs.d(409): Error: cannot modify const expression currParent
If I make path()
@trusted
and non-const instead of @safe const
and parents
non-const the code compiles which may be acceptable but definitely not pretty.
Is it possible to declare a mutable array of const class Dir
-references (parents
) and
a mutable reference to a const object (pathSlow
)? If so that would solve this issue in an elegant way.
Note that path()
is a member function of a file system tree structure where each node contains a reference to a instance to class Dir
.
Sounds like you want to use
const(Dir)[] parents;
If Dir is a class, it won't let you do a const reference that can be reassigned (I think this is intended to be changed at some point, there was a pull request for a while, not sure what the current status is), but you can kinda hack around it by making a little array:
const(Dir)[1] pathSlow;
then refer to it as pathSlow[0]
.