with statement not triggering opDispatch?

Alex Parrill via Digitalmars-d digitalmars-d at puremagic.com
Thu Feb 5 08:27:00 PST 2015


DMD does not seem to consider `opDispatch` when looking up 
variables in a `with` block, or . Is this intentional, or a 
bug/oversight?

For example:

	import std.typecons;
	import std.stdio;

	struct MyStruct {
		auto opDispatch(string name)() {
			return name~"!";
		}
	}

	void main() {
		auto obj = MyStruct();
		with(obj)
			writeln(helloworld());
	}

Fails to run with the following error:

	$ rdmd test.d
	test.d(14): Error: undefined identifier helloworld
	Failed: ["dmd", "-v", "-o-", "test.d", "-I."]

Even though `helloworld` should be "defined", by way of the 
`opDispatch` template.

This also occurs when looking up identifiers in methods, when not 
prefixing the identifiers with `this`:

	import std.typecons;
	import std.stdio;

	struct MyStruct {
		auto opDispatch(string name)() {
			return name~"!";
		}

		void run() {
			writeln(helloworld()); // Error: no identifier `helloworld`
		}
	}

	void main() {
		auto obj = MyStruct();
		obj.run();
	}

I can work around it via introducing a wrapper struct that 
contains the wrapped struct and uses `alias this` on it, which 
fixes the identifier resolution with methods, but not with `with`:

	import std.typecons;
	import std.stdio;

	struct MyStruct {
		auto opDispatch(string name)() {
			return name~"!";
		}
	}

	struct MyStructWrapper {
		MyStruct __mystruct;
		alias __mystruct this;

		void run() {
			writeln(helloworld()); // Prints "helloworld!"
		}
	}

	void main() {
		auto obj = MyStructWrapper();
		obj.run();
		with(obj) writeln(helloworld()); // Still fails
	}

My use case for this is a D implementation of Mustache that 
compiles templates at compile-time, and can be used with 
arbitrary objects. The structure maintains the context stack 
(stored as a tuple), with `opDispatch` forwarding accesses to the 
first object in the stack that contains the named identifier. The 
tag content would be retrieved like `with(context) return 
mixin(tag_content);`, so that `{{helloworld}}` would generate 
`with(context) return helloworld;`.


More information about the Digitalmars-d mailing list