Thread overview
Inference of auto storage classes for interface function return type
Jul 04, 2018
Timoses
Jul 04, 2018
Nicholas Wilson
Jul 04, 2018
Jonathan M Davis
Jul 04, 2018
Timoses
Jul 04, 2018
ag0aep6g
July 04, 2018
How can I return inferred storage class from interface functions?
I can't use auto as return value in interface. Neither can I use "inout" as I don't pass a parameter.

	// Ref Type
	interface IRef
	{
		Ref opIndex(size_t idx) const;
	}
	class CRef : IRef
	{
		Ref[] a;
		this() immutable
		{ this.a = [new Ref()]; }
		Ref opIndex(size_t idx) const
		{ return a[idx]; } // Error: cannot implicitly convert expression this.a[idx] of type const(Ref) to app.Ref
	}
	class Ref{}

	void main()
	{
		auto a = new immutable(CRef)();
		auto s = a[3];
	}

For value types it works, I presume since they are passed by value, so the instance returned is an actual copy of the stored value.

        // Value Type
	interface IValue
	{
		Value opIndex(size_t idx) const;
	}
	class CValue : IValue
	{
		this() immutable { i = [Value()]; }
		Value[] i;
		Value opIndex(size_t idx) const
		{ return i[idx]; }
	}
	struct Value{}

However, for ref types this doesn't work.

Do I have to define two `opIndex` in the interface? One mutable, one for immutable type instances?
July 04, 2018
On Wednesday, 4 July 2018 at 14:07:35 UTC, Timoses wrote:
> How can I return inferred storage class from interface functions?
> I can't use auto as return value in interface. Neither can I use "inout" as I don't pass a parameter.
>
> 	// Ref Type
> 	interface IRef
> 	{
> 		Ref opIndex(size_t idx) const;
> 	}
> 	class CRef : IRef
> 	{
> 		Ref[] a;
> 		this() immutable
> 		{ this.a = [new Ref()]; }
> 		Ref opIndex(size_t idx) const
> 		{ return a[idx]; } // Error: cannot implicitly convert expression this.a[idx] of type const(Ref) to app.Ref
> 	}
> 	class Ref{}
>
> 	void main()
> 	{
> 		auto a = new immutable(CRef)();
> 		auto s = a[3];
> 	}
>
> For value types it works, I presume since they are passed by value, so the instance returned is an actual copy of the stored value.
>
>         // Value Type
> 	interface IValue
> 	{
> 		Value opIndex(size_t idx) const;
> 	}
> 	class CValue : IValue
> 	{
> 		this() immutable { i = [Value()]; }
> 		Value[] i;
> 		Value opIndex(size_t idx) const
> 		{ return i[idx]; }
> 	}
> 	struct Value{}
>
> However, for ref types this doesn't work.
>
> Do I have to define two `opIndex` in the interface? One mutable, one for immutable type instances?

IIRC to apply inout to the this pointer:

Ref opIndex(size_t idx) inout;

or
inout(Ref) opIndex(size_t idx) inout;

not sure off the top of my head,
July 04, 2018
On Wednesday, July 04, 2018 14:07:35 Timoses via Digitalmars-d-learn wrote:
> How can I return inferred storage class from interface functions? I can't use auto as return value in interface. Neither can I use "inout" as I don't pass a parameter.
>
>   // Ref Type
>   interface IRef
>   {
>       Ref opIndex(size_t idx) const;
>   }
>   class CRef : IRef
>   {
>       Ref[] a;
>       this() immutable
>       { this.a = [new Ref()]; }
>       Ref opIndex(size_t idx) const
>       { return a[idx]; } // Error: cannot implicitly convert
> expression this.a[idx] of type const(Ref) to app.Ref
>   }
>   class Ref{}
>
>   void main()
>   {
>       auto a = new immutable(CRef)();
>       auto s = a[3];
>   }
>
> For value types it works, I presume since they are passed by value, so the instance returned is an actual copy of the stored value.
>
>          // Value Type
>   interface IValue
>   {
>       Value opIndex(size_t idx) const;
>   }
>   class CValue : IValue
>   {
>       this() immutable { i = [Value()]; }
>       Value[] i;
>       Value opIndex(size_t idx) const
>       { return i[idx]; }
>   }
>   struct Value{}
>
> However, for ref types this doesn't work.
>
> Do I have to define two `opIndex` in the interface? One mutable, one for immutable type instances?

You can make opIndex inout instead of const. That way, inout applies to the invisible this reference, just like it would with const.

- Jonathan M Davis

July 04, 2018
On Wednesday, 4 July 2018 at 15:12:15 UTC, Jonathan M Davis wrote:
>
> You can make opIndex inout instead of const. That way, inout applies to the invisible this reference, just like it would with const.

Awww, thanks! I was kinda hovering around this[1] section and didn't quite see the MemberFunctionAttribute list[2]. Is there no further description of the behaviour with the inout attribute other than for parameters[1] in the spec?
There's an empty 19.10.10 point without content[3] : D. Maybe a placeholder?

[1]: https://dlang.org/spec/function.html#inout-functions
[2]: https://dlang.org/spec/function.html#MemberFunctionAttribute
[3]: https://dlang.org/spec/function.html#inout-functions
July 04, 2018
On 07/04/2018 05:59 PM, Timoses wrote:
> There's an empty 19.10.10 point without content[3] : D. Maybe a placeholder?
[...]
> [3]: https://dlang.org/spec/function.html#inout-functions

Just a bug.

https://github.com/dlang/dlang.org/pull/2407