Info
-
Did you know that C++20 added
Using Enum
which introduces the enumerator names of the named enumeration as if by a using-declaration for each enumerator?
Example
enum quantlab { dev, research, };
struct Quantlab {
using enum quantlab;
};
int main() {
std::cout << Quantlab::dev; // prints 0
std::cout << Quantlab{}.research; // prints 1
}
Puzzle
- Can you introduce missing enumerators by applying
using Enum
and addis_enum_in_scope
routine to verify whether an enum is in a given scope?
enum E { e1, e2 };
enum class EC { ec1, ec2, };
enum class ECT : int { ect1, ect2 };
struct UsingEnum {
// TODO
};
static_assert(0 == UsingEnum::e1);
static_assert(1 == UsingEnum::e2);
static_assert([](auto t) { return requires { t.e1; }; }(UsingEnum{}));
static_assert([](auto t) { return requires { t.e2; }; }(UsingEnum{}));
struct UsingEnumValue {
// TODO
};
static_assert(0 == UsingEnumValue::e1);
static_assert([](auto t) { return requires { t.e1; }; }(UsingEnumValue{}));
static_assert(not [](auto t) { return requires { t.e2; }; }(UsingEnumValue{}));
struct UsingEnumsMix {
// TODO
};
static_assert(1 == UsingEnumsMix::e2);
static_assert(0 == int(UsingEnumsMix::ec1));
static_assert(0 == int(UsingEnumsMix::ect1));
static_assert(1 == int(UsingEnumsMix::ect2));
static_assert(not [](auto t) { return requires { t.e1; }; }(UsingEnumsMix{}));
static_assert(not [](auto t) { return requires { t.ec2; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.e2; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.ec1; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.ect1; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.ect2; }; }(UsingEnumsMix{}));
template<class T>
constexpr auto is_enum_in_scope(auto expr) { /*TODO*/ return false; }
struct NotInScope {};
static_assert(not is_enum_in_scope<NotInScope>([](auto e){ return requires { e.ec1; }; }));
struct InScope {
using enum EC;
};
static_assert(is_enum_in_scope<InScope>([](auto e){ return requires { e.ec1; }; }));
Solutions
enum E { e1, e2 };
enum class EC { ec1, ec2, };
enum class ECT : int { ect1, ect2 };
struct UsingEnum {
using enum E;
};
static_assert(0 == UsingEnum::e1);
static_assert(1 == UsingEnum::e2);
static_assert([](auto t) { return requires { t.e1; }; }(UsingEnum{}));
static_assert([](auto t) { return requires { t.e2; }; }(UsingEnum{}));
struct UsingEnumValue {
using E::e1;
};
static_assert(0 == UsingEnumValue::e1);
static_assert([](auto t) { return requires { t.e1; }; }(UsingEnumValue{}));
static_assert(not [](auto t) { return requires { t.e2; }; }(UsingEnumValue{}));
struct UsingEnumsMix {
using E::e2;
using EC::ec1;
using enum ECT;
};
static_assert(1 == UsingEnumsMix::e2);
static_assert(0 == int(UsingEnumsMix::ec1));
static_assert(0 == int(UsingEnumsMix::ect1));
static_assert(1 == int(UsingEnumsMix::ect2));
static_assert(not [](auto t) { return requires { t.e1; }; }(UsingEnumsMix{}));
static_assert(not [](auto t) { return requires { t.ec2; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.e2; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.ec1; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.ect1; }; }(UsingEnumsMix{}));
static_assert([](auto t) { return requires { t.ect2; }; }(UsingEnumsMix{}));
template<class T>
constexpr auto is_enum_in_scope(auto expr) { return expr(T{}); }
struct NotInScope {};
static_assert(not is_enum_in_scope<NotInScope>([](auto e){ return requires { e.ec1; }; }));
struct InScope {
using enum EC;
};
static_assert(is_enum_in_scope<InScope>([](auto e){ return requires { e.ec1; }; }));