On 08/28/2010 08:29 PM, dsimcha wrote:
An issue that comes up very frequently when trying to use const, pure or
nothrow in generic code is lack of knowledge of whether the functions you're
calling are const/pure/nothrow. For example:
T abs(T num) pure nothrow {
return (num< 0) ? -1 * num : num;
}
Looks pretty good. Won't work with BigInt because opBinary!"*" isn't pure and
can't practically be made pure. A solution I propose is to allow the
annotations @autoconst, @autopure and @autonothrow for template functions.
These would mean "everything I do is const/pure/nothrow as long as all of the
functions I call are const/pure/nothrow". As far as I can tell, this would be
reasonably implementable because the compiler always has the source code to
template functions, unlike non-template functions.
A pure function would be allowed to call an @autopure function instantiated
with a type that makes it pure, and similarly for const and nothrow. Taking
the address of an instantiation of an @autopure function would return a pure
function pointer iff the instantiation was pure. If an @autopure function
tried to do anything impure other than call an impure function, ideally the
result would not compile, since the function is falsely asserting that
everything it does itself is pure. This is not an absolute requirement, though.
I believe that this would massively simplify correctly using
const/pure/nothrow in generic code, which currently is near impossible. Does
this sound like it could feasibly be implemented and would work well?
Yah, with the growing interest in applying qualifiers at a larger scale
(and making Phobos a good example of such) this is quite timely. I've
been mulling myself over a similar proposal.
What I had in mind is a bit more structured - it would allow selecting a
type or an expression and assessing its constness/purity. That would be
done just like .sizeof and .stringof work - by defining two more special
members .constof, .pureof, .nothrowof. For example:
T abs(T num) (-1 * num).pureof (-1 * num).nothrowof {
return (num < 0) ? -1 * num : num;
}
The @autoxxx stuff arguably makes this example and probably many others
easier to write. What I fear in the case of @autoxxx is that the
compiler will be unable to decide cases in which there are cycles of
@autoxxx.
Andrei