www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why does templated interface function return something different than

reply Timoses <timosesu gmail.com> writes:
Why is the interface templated function not also returning the 
class C toString return value "in C"??

	interface iface
	{
		void toString(scope void delegate(const(char)[]) sink) const;

		final string convert() inout
		{
			import std.conv;
			// assert(std.conv.to!string(this) == "in C"); // fails!
			return std.conv.to!string(this);
		}

		final string convert2() const
		{
			import std.conv;
			assert(std.conv.to!string(this) == "in C");
			return std.conv.to!string(this);
		}
	}

	class C : iface
	{
		void toString(scope void delegate(const(char)[]) sink) const
		{
			sink("in C");
		}
	}

	void main ()
	{
		iface i = new C();
		import std.stdio;
		writeln(i.convert); // "app.C"
		writeln(i.convert2()); // "in C"
	}

It seems like `inout` triggers some odd behaviour??
Jul 18 2018
next sibling parent Timoses <timosesu gmail.com> writes:
On Wednesday, 18 July 2018 at 11:09:12 UTC, Timoses wrote:
 Why is the interface templated function not also returning the 
 class C toString return value "in C"??

 	interface iface
 	{
 		void toString(scope void delegate(const(char)[]) sink) const;

 		final string convert() inout
 		{
 			import std.conv;
 			// assert(std.conv.to!string(this) == "in C"); // fails!
 			return std.conv.to!string(this);
 		}

 		final string convert2() const
 		{
 			import std.conv;
 			assert(std.conv.to!string(this) == "in C");
 			return std.conv.to!string(this);
 		}
 	}

 	class C : iface
 	{
 		void toString(scope void delegate(const(char)[]) sink) const
 		{
 			sink("in C");
 		}
 	}

 	void main ()
 	{
 		iface i = new C();
 		import std.stdio;
 		writeln(i.convert); // "app.C"
 		writeln(i.convert2()); // "in C"
 	}

 It seems like `inout` triggers some odd behaviour??
Sorry, I experimented a bit and forgot to change the topic to something more fitting, e.g. "Why does inout struct function return different results?"
Jul 18 2018
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/18/18 7:09 AM, Timoses wrote:
 Why is the interface templated function not also returning the class C 
 toString return value "in C"??
 
      interface iface
      {
          void toString(scope void delegate(const(char)[]) sink) const;
 
          final string convert() inout
          {
              import std.conv;
              // assert(std.conv.to!string(this) == "in C"); //
fails!
              return std.conv.to!string(this);
          }
 
          final string convert2() const
          {
              import std.conv;
              assert(std.conv.to!string(this) == "in C");
              return std.conv.to!string(this);
          }
      }
 
      class C : iface
      {
          void toString(scope void delegate(const(char)[]) sink) const
          {
              sink("in C");
          }
      }
 
      void main ()
      {
          iface i = new C();
          import std.stdio;
          writeln(i.convert); // "app.C"
          writeln(i.convert2()); // "in C"
      }
 
 It seems like `inout` triggers some odd behaviour??
Looking at the AST, it appears that toImpl doesn't recognize what inout(iface) is: toImpl!(string, inout(iface)) { system string toImpl(ref inout(iface) value) { import std.array : appender; import std.format : FormatSpec, formatValue; Appender!string w = appender(); FormatSpec!char f = FormatSpec; formatValue(w, value, f); return w.data(); } } Vs. the nice neat call for const(iface) toImpl!(string, const(iface)) { system string toImpl(const(iface) value) { return toStr(value); } } Note the ref there, too. This means it can't cast to const. I wonder if that's an issue. -Steve
Aug 02 2018
parent reply Timoses <timosesu gmail.com> writes:
On Thursday, 2 August 2018 at 20:35:57 UTC, Steven Schveighoffer 
wrote:
 Looking at the AST, it appears that toImpl doesn't recognize 
 what inout(iface) is:

 toImpl!(string, inout(iface))
 {
 	 system string toImpl(ref inout(iface) value)
 	{
 		import std.array : appender;
 		import std.format : FormatSpec, formatValue;
 		Appender!string w = appender();
 		FormatSpec!char f = FormatSpec;
 		formatValue(w, value, f);
 		return w.data();
 	}

 }

 Vs. the nice neat call for const(iface)

 toImpl!(string, const(iface))
 {
 	 system string toImpl(const(iface) value)
 	{
 		return toStr(value);
 	}

 }

 Note the ref there, too. This means it can't cast to const. I 
 wonder if that's an issue.

 -Steve
Thanks for the insight. To me it sounds like std.conv `toImpl` doesn't properly handle inout types in this case.
Aug 06 2018
parent Timoses <timosesu gmail.com> writes:
On Monday, 6 August 2018 at 14:27:01 UTC, Timoses wrote:
 On Thursday, 2 August 2018 at 20:35:57 UTC, Steven 
 Schveighoffer wrote:
 Looking at the AST, it appears that toImpl doesn't recognize 
 what inout(iface) is:

 toImpl!(string, inout(iface))
 {
 	 system string toImpl(ref inout(iface) value)
 	{
 		import std.array : appender;
 		import std.format : FormatSpec, formatValue;
 		Appender!string w = appender();
 		FormatSpec!char f = FormatSpec;
 		formatValue(w, value, f);
 		return w.data();
 	}

 }

 Vs. the nice neat call for const(iface)

 toImpl!(string, const(iface))
 {
 	 system string toImpl(const(iface) value)
 	{
 		return toStr(value);
 	}

 }

 Note the ref there, too. This means it can't cast to const. I 
 wonder if that's an issue.

 -Steve
Thanks for the insight. To me it sounds like std.conv `toImpl` doesn't properly handle inout types in this case.
Well, my "workaround" now is to simply cast the inout type to const before passing to std.conv.to ... I've experimented a bit more and compiled it a bit together. import std.stdio; import std.conv : to; interface I { void toString(scope void delegate(const(char)[]) sink) const; final void printI() { writeln(this.to!string); // this is class A } final void printIinout() inout { writeln(this.to!string); // app.A } } class A : I { void print() { writeln(this.to!string); // this is class A } // Compilation error // std\format.d(3890,13): Error: template instance `std.format.formatObject!(Appender!string, inout(A), char)` does not match template declaration `formatObject(Writer, T, Char)(ref Writer w, ref T val, ref const FormatSpec!Char f) if (hasToString!(T, Char))` /*void printinout() inout { writeln(this.to!string); }*/ override void toString(scope void delegate(const(char)[]) sink) const { sink("this is class A"); } } unittest { I i = new A(); i.printI(); i.printIinout(); A a = new A(); a.print(); //a.printinout(); } It seems inconsistent to me. What do you think? Should I open a bug report for this? Also the compilation error should not occur, should it?
Aug 08 2018