D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.

Issue 4413

Summary: typeof(this) doesn't work in method template signature
Product: D Reporter: bearophile_hugs
Component: dmdAssignee: No Owner <nobody>
Status: RESOLVED FIXED
Severity: normal CC: akb825, bugzilla, code, ibuclaw, kennytm
Priority: P2 Keywords: patch, rejects-valid
Version: D2
Hardware: All
OS: All

Description bearophile_hugs 2010年07月01日 14:27:43 UTC
dmd v2.047 shows a compilation error on the call to bar4, but in my opinion the compiler has to compile all four those bar methods:
struct Foo {
 alias typeof(this) typeof_this;
 void bar1(typeof_this other) {}
 void bar2()(typeof_this other) {}
 void bar3(typeof(this) other) {}
 void bar4()(typeof(this) other) {}
}
void main() {
 Foo f;
 f.bar1(f); // OK
 f.bar2(f); // OK
 f.bar3(f); // OK
 f.bar4(f); // ERR
}
The generated errors:
test.d(13): Error: template test.Foo.bar4() does not match any function template declaration
test.d(13): Error: template test.Foo.bar4() cannot deduce template function from argument types !()(Foo)
The problem of bar4 has shown up in D2 code similar to this one, where I have used typeof(this) to follow the DRY strategy and avoid repeating the struct name more than one time:
struct Vec2 {
 float x, y;
 auto opBinary(string op)(typeof(this) other) if (op == "+") {
 ...
 }
}
A workaround that can be used is:
struct Vec2 {
 float x, y;
 alias typeof(this) typeof_this;
 auto opBinary(string op)(typeof_this other) if (op == "+") {
 ...
 }
}
Comment 1 Iain Buclaw 2011年02月06日 07:32:03 UTC
Calling semantic on the param type in ::deduceType seems to be simplest workaround without causing side effects.
--- a/src/template.c
+++ b/src/template.c
@@ -2183,6 +2183,7 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
 * to a template instance, too, and try again.
 */
 TemplateInstance *ti = sym->parent->isTemplateInstance();
+ tparam = tparam->semantic(0, sc);
 
 if (tparam && tparam->ty == Tinstance)
 {
@@ -2317,6 +2318,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
 * to a template instance, too, and try again.
 */
 TemplateInstance *ti = sym->parent->isTemplateInstance();
+ tparam = tparam->semantic(0, sc);
 
 if (tparam && tparam->ty == Tinstance)
 {
Ideally though, all typeof()'s should have been expanded beforehand.
Regards
Comment 2 bearophile_hugs 2011年02月06日 11:58:12 UTC
*** Issue 5532 has been marked as a duplicate of this issue. ***
Comment 3 David Nadlinger 2011年03月30日 17:53:08 UTC
The patch by Iain seems to break std.datetime:
/usr/local/include/d2/std/datetime.d(9217): Error: template instance std.datetime.DTRebindable!(immutable(TimeZone)) error instantiating
Comment 4 Iain Buclaw 2011年03月31日 05:43:42 UTC
(In reply to comment #3)
> The patch by Iain seems to break std.datetime:
> 
> /usr/local/include/d2/std/datetime.d(9217): Error: template instance
> std.datetime.DTRebindable!(immutable(TimeZone)) error instantiating
Yep, I was merely suggesting that things should ideally be worked out before this point (because they *can* be worked out).
Comment 5 Kenji Hara 2011年12月21日 05:55:25 UTC
*** Issue 5801 has been marked as a duplicate of this issue. ***
Comment 6 Kenji Hara 2011年12月21日 05:55:58 UTC
https://github.com/D-Programming-Language/dmd/pull/572 
Comment 8 Kenji Hara 2012年04月23日 17:04:51 UTC
*** Issue 5903 has been marked as a duplicate of this issue. ***

AltStyle によって変換されたページ (->オリジナル) /