is_complete is a pure footgun. You can write it in pure C++ today, but there are many questions about how it behaves, that can really only be answered with "UB" or IFNDR. For example:
struct S;
constexpr bool A = std::is_complete_v<S>;struct S{};
constexpr bool B = std::is_complete_v<S>; // What's the value of B here?
Or
// Foo.hpp
template<typename T> int break_the_world(){
if constexpr(std::is_complete_v<T>)
return 42;
else
return 1337;
}
// A.cpp
#include "Foo.hpp"
struct S;
void foo(){
break_the_world<S>();
}
// B.cpp
#include "Foo.hpp"
struct S{};
void foo(){
break_the_world<S>();
}