303
303

Reputation: 4732

Recursive template instantiation

Is the following code (live example) conformant to the C++20 specifications? And why or why not? Clang and GCC seem to be in disagreement as Clang 14.0.0 happily compiles the given example.

struct s {
    template<typename T>
    inline static auto f
        = [](){ return T::template g<s>; };
};

struct t {
    template<typename T>
    inline static auto g
        = [](){ return T::template f<t>; };
};

auto main() -> int {
    s::f<t>();
}

The error produced by GCC 12.1:

<source>:4:36:   required from 'auto s::f<t>'
<source>:14:8:   required from here
<source>:10:36: error: use of 's::f<t>' before deduction of 'auto'
   10 |         = [](){ return T::template f<t>; };
      |                        ~~~~~~~~~~~~^~~~
<source>:10:36: error: use of 's::f<t>' before deduction of 'auto'

Interestingly, when invoking the instantion of s::f, as in s::f<t>()();, Clang seems to give out completely.

Upvotes: 4

Views: 162

Answers (1)

Davis Herring
Davis Herring

Reputation: 39818

I don’t think the standard gives any satisfactory answer here because it doesn’t describe the process of template instantiation in any detail. The practical problem is of course that each closure type is the return type of the other, so that it depends on how the implementation creates the closure types: if it decides that the type of the static member variable template specialization is the closure type and then processes its operator(), it works, and if it does these in the other order it doesn’t. Note that the lambdas copy one another, so the compiler has to have analyzed the (defaulted) copy constructor too.

Upvotes: 1

Related Questions