bloomberg / clang-p2996

Experimental clang support for WG21 P2996 (Reflection).
https://github.com/bloomberg/clang-p2996/tree/p2996/P2996.md
51 stars 8 forks source link

call to immediate function is not a constant expression #62

Closed Yaraslaut closed 2 months ago

Yaraslaut commented 2 months ago

I stumbled in weird compiler error, code in question : https://godbolt.org/z/Yox46WPMd in short

constexpr auto reflA = ^A;
form::util::printMembers<[:reflA:]>(); // <------ works
constexpr auto refl = CreateClass<CreateUniqueT<int>>();
form::util::printMembers<[:refl:]>(); // <---  error: call to immediate function 'form::util::printMembers<CreateUniqueT<int, (lambda at <source>:97:45)>>' is not a constant expression
katzdm commented 2 months ago

Hey @Yaraslaut - Here is what's happening.

Based on the above, I believe the issue is with your example - I'm going to close, but please re-open if I've missed something!

Yaraslaut commented 2 months ago

Thanks @katzdm for the detailed explanation, I indeed forgot that I changed the signature of name_of and if i keep string_view than everything is fine, thanks. I am still a bit confused why it is working for declared type, but not for defined through define_class call

katzdm commented 2 months ago

Ah! Good point, and the reason is actually pretty fun - libcxx implements a "short string optimization" in the std::string implementation, which stores small strings in a static buffer. In the case of the compiler running on godbolt, as many as (but no more than) 22 characters (including the null terminator) can be stored before a dynamic allocation occurs. The name rendered for CreateUniqueT<int, (lambda at /app/example.cpp:96:45)> is what overruns that 22 character limit, thus triggering a dynamic allocation and rendering the call not-constexpr.

All of that said, there is a subtle bug here: the name returned by name_of here should just be CreateUniqueT; the P2996 spec states that name_of should not include the names of template arguments.