digitalmars.D.learn - overloads and parents. __traits confusion
- John Colvin (21/21) Aug 11 2014 can someone talk me through the reasoning behind this:
- Dicebot (3/4) Aug 11 2014 Say hello to optional parens - you are trying to call foo!float()
- John Colvin (18/22) Aug 12 2014 I thought so. Ugh.
- anonymous (34/55) Aug 12 2014 (I'm not sure if the following is completely correct, but it
can someone talk me through the reasoning behind this: import std.typetuple; void foo(T)(T v){} void foo(){} version(ThisCompiles) { alias Parent = TypeTuple!(__traits(parent, foo))[0]; pragma(msg, __traits(getOverloads, Parent, "foo")); // tuple() } else { alias Parent = TypeTuple!(__traits(parent, foo!float))[0]; pragma(msg, __traits(getOverloads, Parent, "foo")); /* /d54/f131.d(8): Error: foo (float v) is not callable using argument types () /d54/f131.d(8): Error: (__error).foo cannot be resolved tuple() */ }
Aug 11 2014
On Monday, 11 August 2014 at 13:00:27 UTC, John Colvin wrote:alias Parent = TypeTuple!(__traits(parent, foo!float))[0];Say hello to optional parens - you are trying to call foo!float() here and apply result to trait.
Aug 11 2014
On Tuesday, 12 August 2014 at 05:23:53 UTC, Dicebot wrote:On Monday, 11 August 2014 at 13:00:27 UTC, John Colvin wrote:I thought so. Ugh. This works though: void foo(float v){} void foo(int a){} alias Parent = TypeTuple!(__traits(parent, foo))[0]; pragma(msg, __traits(getOverloads, Parent, "foo")); so it seems that instantiated function templates in this case are called parenthesis-free, whereas normal functions are passed by name/alias/whatever. All expressions that are used as compile-time args (whether in udas, traits or as template arguments) should require parenthesis to be called. Anything else is madness. A!(foo1().foo2()) //pass result A!(foo1.foo2()) //pass result A!(foo1.foo2) //pass function A!(foo1) //pass function foo(foo1) //pass resultalias Parent = TypeTuple!(__traits(parent, foo!float))[0];Say hello to optional parens - you are trying to call foo!float() here and apply result to trait.
Aug 12 2014
On Monday, 11 August 2014 at 13:00:27 UTC, John Colvin wrote:can someone talk me through the reasoning behind this: import std.typetuple; void foo(T)(T v){} void foo(){} version(ThisCompiles) { alias Parent = TypeTuple!(__traits(parent, foo))[0]; pragma(msg, __traits(getOverloads, Parent, "foo")); // tuple() } else { alias Parent = TypeTuple!(__traits(parent, foo!float))[0]; pragma(msg, __traits(getOverloads, Parent, "foo")); /* /d54/f131.d(8): Error: foo (float v) is not callable using argument types () /d54/f131.d(8): Error: (__error).foo cannot be resolved tuple() */ }(I'm not sure if the following is completely correct, but it makes a lot of sense to me at the moment.) For clarity, the verbose version of that template: template foo(T) /* the (eponymous) template */ { void foo(T v) {} /* the function; the eponymous member */ } foo is the template: `foo.stringof` = "foo(T)(T v)". Its parent is the module: `__traits(parent, foo).stringof` = "module test". This is what you use in version(ThisCompiles). No problems. foo!float is an instance of the template. Since the template is eponymous, instantiations resolve to the eponymous member, always. So foo!float is the function: `foo!float.mangleof.demangle` = "pure nothrow nogc safe void test7.foo!(float).foo(float)" Its parent is the template instance, which resolves right back to the function: `__traits(parent, foo!float).mangleof.demangle` = "pure nothrow nogc safe void test7.foo!(float).foo(float)" (just foo!float again) Apparently, you cannot get out of an eponymous template instantiation with __traits(parent, ...). Maybe __traits(parent, ...) of an eponymous template instance should be the parent of the template. The current behaviour seems useless to me. Simple test case without functions (no additional trouble from optional parentheses): struct S(T) {} /* All print "S!int": */ pragma(msg, S!int); pragma(msg, __traits(parent, S!int)); pragma(msg, __traits(parent, __traits(parent, S!int)));
Aug 12 2014