www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is this a compiler error? "recursive template expansion"

reply Nathan S. <no.public.email example.com> writes:
The following code fails to compile. Is this a compiler error or 
if not what is wrong with the code?

---
struct Template2(T)
{
     // If both of the following are removed compilation succeeds
     // without any other changes:
     enum tString = T.stringof;
     static if (is(T == class))
         enum tLinkage = __traits(getLinkage, T);
}

struct Template1(Param1, Param2 = Template2!Param1) {}

// Moving the definition of AliasTemplate1S after the definition 
of S
// causes compilation to succeed without any other changes.
alias AliasTemplate1S = Template1!S;

class S
{
     // If the following line is removed compilation succeeds
     // without any other changes.
     Template1!int x;
}

void main()
{
}
---

Failure message:
main.d(20): Error: struct main.Template1(Param1, Param2 = 
Template2!Param1) recursive template expansion
main.d(20):        while looking for match for Template1!int
main.d(7): Error: class S is forward referenced
main.d(10): Error: template instance main.Template2!(S) error 
instantiating
main.d(14):        instantiated from here: Template1!(S)
Dec 08 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Tuesday, 8 December 2020 at 20:11:40 UTC, Nathan S. wrote:
 The following code fails to compile. Is this a compiler error 
 or if not what is wrong with the code?
What is wrong is that partial specialization is not correct. The correct partial specialization is: --- struct Template2(T) { enum tString = T.stringof; static if (is(T == class)) enum tLinkage = __traits(getLinkage, T); } struct Template1(Param1, Param2 = Template2!Param1) {} alias AliasTemplate1S(SecondParam) = Template1!(S,SecondParam); // ^here class S { Template1!int x; } --- Now that being said, the compiler could complain about the incorrect partial spec instead of falling in the nonsensical error message. There is a gap because the second template param looks optional so you dont put it the partial specialization but it is still required. Anyway. This case is either a "bad diagnostic" or an "enhancement" request. Or should be specified.
Dec 08 2020
parent Nathan S. <no.public.email example.com> writes:
On Tuesday, 8 December 2020 at 22:01:52 UTC, Basile B. wrote:
 On Tuesday, 8 December 2020 at 20:11:40 UTC, Nathan S. wrote:
 The following code fails to compile. Is this a compiler error 
 or if not what is wrong with the code?
What is wrong is that partial specialization is not correct. The correct partial specialization is: --- struct Template2(T) { enum tString = T.stringof; static if (is(T == class)) enum tLinkage = __traits(getLinkage, T); } struct Template1(Param1, Param2 = Template2!Param1) {} alias AliasTemplate1S(SecondParam) = Template1!(S,SecondParam); // ^here class S { Template1!int x; } --- Now that being said, the compiler could complain about the incorrect partial spec instead of falling in the nonsensical error message. There is a gap because the second template param looks optional so you dont put it the partial specialization but it is still required. Anyway. This case is either a "bad diagnostic" or an "enhancement" request. Or should be specified.
Thanks a lot! In my case what I was intending was: alias AliasTemplate1S = Template1!(S, Template2!S) which as you suggest works fine. It's a bit odd that the non-optional second parameter becomes optional again if declaration order is shuffled, but my motivation to look into this has temporarily abated since it's no longer stopping me from doing something else. For the program where I ran into this problem the most convenient fix turns out to be to get rid of the default template parameter and instead use a pattern like this: --- struct Template1(Param1, Param2) {} alias Template1(Param1) = Template1!(Param1, Template2!Param1); ---
Dec 08 2020