Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive template instantiation

Tags:

c++

c++20

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.

like image 905
303 Avatar asked Apr 07 '26 23:04

303


1 Answers

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.

like image 82
Davis Herring Avatar answered Apr 09 '26 14:04

Davis Herring