Skip to content

Latest commit

 

History

History
128 lines (101 loc) · 3.98 KB

202.md

File metadata and controls

128 lines (101 loc) · 3.98 KB
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
}

https://godbolt.org/z/jf4d8Kc

Puzzle

  • Can you introduce missing enumerators by applying using Enum and add is_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; }; }));

https://godbolt.org/z/ocs9ME

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; }; }));

https://godbolt.org/z/KvYYKM