www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Inference of auto storage classes for interface function return type

reply Timoses <timosesu gmail.com> writes:
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?
Jul 04 2018
next sibling parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
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,
Jul 04 2018
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Jul 04 2018
parent reply Timoses <timosesu gmail.com> writes:
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
Jul 04 2018
parent ag0aep6g <anonymous example.com> writes:
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
Jul 04 2018