digitalmars.D.learn - Eponymous template with full template syntax
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (18/18) Jul 01 2013 I think main's second line used to work:
- Jonathan M Davis (9/31) Jul 01 2013 I'm not aware of it ever having worked, but given that the whole point o...
- Maxim Fomin (7/27) Jul 01 2013 I think that this probably worked as early as in the end of 2011
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (35/41) Jul 01 2013 To answer Jonathan's question as well, it must have worked because I see...
- monarch_dodra (17/63) Jul 01 2013 I though UFCS wasn't possible with constructors? *That* very
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (43/51) Jul 01 2013 I *think* I did not know it but I can't be sure. :)
- monarch_dodra (6/11) Jul 01 2013 AH... I looked at the threads some more: I was actually thinking
- Steven Schveighoffer (7/25) Jul 01 2013 =
I think main's second line used to work: template isSmall(T) { enum isSmall = (T.sizeof < 12345); } void main() { static assert(isSmall!int); // <-- the usual syntax works static assert(isSmall!int.isSmall); // <-- compilation ERROR } Error: template deneme.isSmall does not match any function template declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change intentional? Ali
Jul 01 2013
On Monday, July 01, 2013 11:15:04 Ali Çehreli wrote:I think main's second line used to work: template isSmall(T) { enum isSmall = (T.sizeof < 12345); } void main() { static assert(isSmall!int); // <-- the usual syntax works static assert(isSmall!int.isSmall); // <-- compilation ERROR } Error: template deneme.isSmall does not match any function template declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change intentional?I'm not aware of it ever having worked, but given that the whole point of eponymous templates is that they be replaced with the symbol carrying their name and _everything_ else in the template is hidden, I would think that what you're seeing is correct behavior. isSmall!int is replaced with the isSmall within isSmall!int, and isSmall.isSmall makes no sense, so if that was allowed before, I'd definitely argue that disallowing it was a bug fix. - Jonathan m Davis
Jul 01 2013
On Monday, 1 July 2013 at 18:15:06 UTC, Ali Çehreli wrote:I think main's second line used to work: template isSmall(T) { enum isSmall = (T.sizeof < 12345); } void main() { static assert(isSmall!int); // <-- the usual syntax works static assert(isSmall!int.isSmall); // <-- compilation ERROR } Error: template deneme.isSmall does not match any function template declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change intentional? AliI think that this probably worked as early as in the end of 2011 but I can be wrong as don't remember exactly. It seems that dmd recognizes isSmall!int.isSmall as potential UFCS property, converts isSmall!int to bool and tries to issue call isSmall(bool) and fails, because that template does not define any function.
Jul 01 2013
On 07/01/2013 12:03 PM, Maxim Fomin wrote:I think that this probably worked as early as in the end of 2011 but I can be wrong as don't remember exactly.To answer Jonathan's question as well, it must have worked because I see it in code that is definitely tested when it was written.It seems that dmd recognizes isSmall!int.isSmall as potential UFCS property, converts isSmall!int to bool and tries to issue call isSmall(bool) and fails, because that template does not define any function.That explains it. :) Let's play with it a little: import std.stdio; template isSmall(T) { enum isSmall = (T.sizeof < 12345); struct S { T m; } } struct S { int[10] i; } void main() { writeln(isSmall!int); writeln(isSmall!int.S.init); writeln(isSmall!int.S); } First of all, apparently a template can include a definition with the same name but I still cannot type isSmall!int.isSmall. I guess the above is still an eponymous template and isSmall!int still means isSmall!int.isSmall. Now guess what the last two lines print. :) isSmall!int.S is *not* the S that is included in the template! Here is the output: true S([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) S([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) The last line is actually an anonymous struct object of type S (the S that is defined at module level). That is confusing. Ali
Jul 01 2013
On Monday, 1 July 2013 at 20:28:28 UTC, Ali Çehreli wrote:On 07/01/2013 12:03 PM, Maxim Fomin wrote:I though UFCS wasn't possible with constructors? *That* very usecase is one of the reasons why. Shouldn't that be an accepts-invalid?I think that this probably worked as early as in the end of2011 but Ican be wrong as don't remember exactly.To answer Jonathan's question as well, it must have worked because I see it in code that is definitely tested when it was written.It seems that dmd recognizes isSmall!int.isSmall as potentialUFCSproperty, converts isSmall!int to bool and tries to issue call isSmall(bool) and fails, because that template does notdefine anyfunction.That explains it. :) Let's play with it a little: import std.stdio; template isSmall(T) { enum isSmall = (T.sizeof < 12345); struct S { T m; } } struct S { int[10] i; } void main() { writeln(isSmall!int); writeln(isSmall!int.S.init); writeln(isSmall!int.S); } First of all, apparently a template can include a definition with the same name but I still cannot type isSmall!int.isSmall. I guess the above is still an eponymous template and isSmall!int still means isSmall!int.isSmall. Now guess what the last two lines print. :) isSmall!int.S is *not* the S that is included in the template! Here is the output: true S([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) S([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) The last line is actually an anonymous struct object of type S (the S that is defined at module level).That is confusing.UFCS construction: Yes. The rest, not so much: The idea is that once a template is "eponymous", it *fully* becomes the eponymous function/type/value (s). Every other function, regardless of public/private*, simply seizes to exist to the outside world. You can't make a "qualified" call to an eponymous template, because the "qualification" is already the call. Long story short, it's not mix and match: Either you have a normal template, or you have an something eponymous, not a bit of both: *What qualifies for eponymous template is kind of "buggy", since what actually qualifies is not exactly what the spec says. Still, *once* something is considered "qualified" by the implementation, then it is fully eponymous.
Jul 01 2013
On 07/01/2013 02:10 PM, monarch_dodra wrote:I *think* I did not know it but I can't be sure. :) struct S { int i; } void main() { static assert (S(42) == 42.S); } It works with 2.063 (v2.064-devel-a1a1537 too).That is confusing.UFCS construction: Yes.The rest, not so much: The idea is that once a template is "eponymous", it *fully* becomes the eponymous function/type/value (s). Every other function, regardless of public/private*, simply seizes to exist to the outside world. You can't make a "qualified" call to an eponymous template, because the "qualification" is already the call.A single definition with the same name makes it an eponymous template. I used to think that the template should also have a single definition. So, currently other definitions act as implementation details of the template. The following template sees the local S, not the module-level one: struct S { int[10] i; } template epo(T) { size_t epo() { return S.sizeof; // <-- epo.S, not .S } struct S { int i; } double foo() { return 1.5; } } void main() { assert(epo!int() == int.sizeof); // <-- yes, epo.S mixin epo!int; assert(foo() == 1.5); } Also note that mixing in the template is still possible but it is an orthogonal feature anyway. Ali
Jul 01 2013
On Monday, 1 July 2013 at 22:46:55 UTC, Ali Çehreli wrote:On 07/01/2013 02:10 PM, monarch_dodra wrote:AH... I looked at the threads some more: I was actually thinking about a proposal that wanted (just like UFCS), to allow non-intrusively adding constructors. So I guess UFCS and constructors are fair game? I do not like this at all...I *think* I did not know it but I can't be sure. :)That is confusing.UFCS construction: Yes.
Jul 01 2013
On Mon, 01 Jul 2013 14:15:04 -0400, Ali =C3=87ehreli <acehreli yahoo.com=wrote:I think main's second line used to work: template isSmall(T) { enum isSmall =3D (T.sizeof < 12345); } void main() { static assert(isSmall!int); // <-- the usual syntax work=sstatic assert(isSmall!int.isSmall); // <-- compilation ERROR } Error: template deneme.isSmall does not match any function template =declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from==argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change =intentional?I think it used to work, and I think the change was intentional. I also= = "discovered" this not too long ago. -Steve
Jul 01 2013