I'm trying to write a concept that checks if a type is a structural type (can be used as non type parameter in a template). Writing one to check if a default constructable type is structural was quite easy but I can't find a way to express the general requirement as it seems that "requires" parameters can't be "declared" as constexpr.
struct StructuralType1 {
constexpr StructuralType1(int a=42): a(a) {
}
int a;
};
struct StructuralType2 {
constexpr StructuralType2(int a): a(a) {
}
int a;
};
struct NonStructuralType {
constexpr NonStructuralType(int a): a(a) {
}
private:
int a;
};
template <auto T> consteval void is_structural_helper() {
};
template<typename T>
concept is_structural = requires () {
{is_structural_helper<T{}>() }; // T{}
};
// These are ok
static_assert(is_structural<StructuralType1>, "BUG! StructuralType1 is not structural");
static_assert(!is_structural<NonStructuralType>, "BUG! NontStructuralType is structural");
// This fails (StructuralType2 is not default constructable but still is a structural type)
//static_assert(is_structural<StructuralType2>, "BUG! StructuralType2 is not structural");
template <auto X> constexpr int increment() {
return X.a+1;
}
constexpr int fourtytwo=increment<StructuralType2{41}>();
clang++, icx and MSVC accepts this form (and your asserts passes), but unfortunately, gcc doesn't (which thinks even
NonStructuralTypecan be used as a non-type template parameter type). I filed bug #114504 in gcc's bugzilla:Demo