Inout unclearness
Steven Schveighoffer via Digitalmars-d
digitalmars-d at puremagic.com
Mon Jul 13 06:50:01 PDT 2015
On 7/12/15 1:03 AM, Max Klimov wrote:
> inout(A) bar(inout(A) x) // compilation error
> {
> Rebindable!(typeof(return)) r;
> r = x;
> return r;
> }
>
> Rebindable doesn't handle the case of inout type and I don't think that
> it can do it because it is possible to cast to inout or to keep inout
> variables only inside the proper inout function.
So a variable cannot be inout in a struct, because once it leaves the
function, it's not clear how to cast that part of the struct to
something else. In other words, a struct like this:
struct X(T)
{
T t;
}
X!(int) x1;
X!(const(int)) x2 = x1;
Techincally, the assignment should be allowed, but the compiler cannot
see into the template to see if it's actually the same, or even if the
template parameter applies to anything in the struct. One can do
something like:
struct X(T)
{
static if(is(T == const))
bool screwup;
T t;
}
With inout, it's even more tricky, because the compiler has to ensure
it's not inout when it leaves the function. And it's not possible in
some cases to do this.
At the end of the day, this comes down to D not supporting tail-const
classes. If that was supported in the language, this is all doable.
> So, I have to make some
> silly workarounds with castings in this case. The same situation happens
> in several places in phobos when arguments type is deductible. For
> example, std.array.replaceInPlace(...), std.array.join(...), etc, can
> not be used with inout(T) parameters.
Right, this is because it uses generated structs internally.
> The second question: if I want to provide inout function but it fails
> like in the example above, what is common practice? Just use casting? Or
> make a templated version and provide hand-writing code for all cases
> (mutable, const, immutable)? Or something wrong with inout qualifier?
You can simply use a template function without hand-written cases. This
is what inout was meant to replace.
In your example:
T bar(T)(T t) if(is(Unqual!T : A))
{
// same implementation
}
Of course, this doesn't work for inout!A as a parameter, if that is what
you have :)
But you could specifically cast it to/from const, or do something like:
T bar(T)(T t) if(is(Unqual!T : A))
{
static if(is(T == inout))
return cast(T)(.bar(cast(const(Unqual!T))t));
else
{
// real implementation
}
}
-Steve
More information about the Digitalmars-d
mailing list