The whole bunch of "stateful" metaprogramming can be achieved by forcing template reevaluation. Here I don't want to discuss whether one should or should not use or depend on it. But since C++20 has allowed usage of lambdas in unevaluated contexts, I guess the Pandora's Box is now widely open.
The following code now provides expected results, because _is_complete
is now "reevaluated" on each new invocation (technically speaking, old specializations never change, only new ones are introduced).
https://godbolt.org/z/5zv884xvE
#include <cstddef>
#include <type_traits>
template <typename T, auto, typename = void>
struct _is_complete : std::false_type {};
template <typename T, auto A>
struct _is_complete<T, A, std::void_t<decltype(sizeof(T))>> : std::true_type {};
template <typename T, auto A = []{}>
constexpr auto is_complete() noexcept {
return _is_complete<T, A>{};
}
#include <iostream>
int main() {
std::cout << std::boolalpha;
struct incomplete;
std::cout << is_complete<incomplete>() << '\n'; // false
struct incomplete{};
std::cout << is_complete<incomplete>() << '\n'; // true
return 0;
}
This particular code is closelly related to How to write is_complete
template?, but I am more interested in possibility of forcing template reevaluation in general prior to C++20's lambdas.
Please, do not suggest using any kind of macros like __COUNTER__
since it would be useless within a template's declaration.