[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
311 lines (245 loc) · 6.24 KB

270.md

File metadata and controls

311 lines (245 loc) · 6.24 KB
Info

Example

enum { QL = 42 };

int main() {
    std::cout << std::to_underlying(QL); // prints 42
    static_assert(typeid(std::to_underlying(QL)) == typeid(unsigned));
}

https://godbolt.org/z/h8x6zYGGe

Puzzle

  • Can you implement sum_enums which adds only underlying enum values?
template <auto... Ns>
constexpr auto sum_enums = /*TODO*/;

enum { _1 = 1 };
enum class Q2 { _2 = 2 };
enum class Q3 : int { _3 = 3 };

static_assert(0 == sum_enums<42>);
static_assert(1 == sum_enums<_1>);
static_assert(2 == sum_enums<Q2::_2>);
static_assert(3 == sum_enums<Q3::_3>);
static_assert(1 + 2 + 3 == sum_enums<_1, Q2::_2, Q3::_3>);
static_assert(3 + 2 + 1 == sum_enums<Q3::_3, Q2::_2, _1>);
static_assert(3 + 2 + 1 == sum_enums<Q3::_3, Q2::_2, _1, 42>);
static_assert(3 + 2 + 1 == sum_enums<1, Q3::_3, 2, Q2::_2, 3, _1, 4>);

https://godbolt.org/z/fexYEKerY

Solutions

template <auto V>
constexpr auto enum_underlying_or_zero = 0;

template <auto V>
requires requires { std::to_underlying(V); }
constexpr auto enum_underlying_or_zero<V> = std::to_underlying(V);

template <auto... Ns>
constexpr auto sum_enums = (enum_underlying_or_zero<Ns> + ...)

https://godbolt.org/z/jojeGMKqj

template <auto... Ns>
constexpr auto sum_enums = ([](auto val) { 
    if constexpr (std::is_enum_v<decltype(val)>)
        return std::to_underlying(val);
    else
        return 0;
} (Ns) + ...);

https://godbolt.org/z/KKEsM8cdd

namespace detail {

template <typename T>
concept CEnum = std::is_enum_v<T>;

[[nodiscard]] constexpr auto get_enum_value(auto&&) { return 0; }

[[nodiscard]] constexpr auto get_enum_value(const CEnum auto e) {
    return std::to_underlying(e);
}

}  // namespace detail

template <auto... Ns>
constexpr auto sum_enums = (... + detail::get_enum_value(Ns));

https://godbolt.org/z/Ps6ojrv6v

namespace detail {
    template <auto v>
    constexpr auto value = []{
        if constexpr (std::is_enum_v<decltype(v)>) {
            return std::to_underlying(v);
        } else {
            return 0;
        }
    };
}
template <auto... Ns>
constexpr auto sum_enums = [] {
    return (detail::value<Ns>() + ...);
}();

https://godbolt.org/z/rhrrP71dP

template <auto N>
constexpr auto underlying_value = [] {
  if constexpr (requires {std::to_underlying(N);}) {
    return std::to_underlying(N);
  } else {
    return decltype(N){};
  }
};

template <auto... Ns>
constexpr auto sum_enums = (underlying_value<Ns>() + ... + 0);

https://godbolt.org/z/zGdGo93YM

template<typename ValT>
requires std::integral<ValT>
constexpr auto get_return_val(ValT const& val){
    return 0;
}

template<typename ValT>
constexpr auto get_return_val(ValT const& val){
    return std::to_underlying(val);
}

template<typename... Ns>
constexpr auto sum(Ns const&... n){
    return ( get_return_val(n) + ...);
}

template <auto... Ns>
constexpr auto sum_enums = [](){
    return sum(Ns...);
}();

https://godbolt.org/z/KPEWvjsK3

template<typename ValT>
requires std::integral<ValT>
constexpr auto get_return_val(ValT const& val){
    return 0;
}

template<typename ValT>
constexpr auto get_return_val(ValT const& val){
    return std::to_underlying(val);
}

template<typename... Ns>
constexpr auto sum(Ns const&... n){
    return ( get_return_val(n) + ...);
}

template <auto... Ns>
constexpr auto sum_enums = [](){
    return sum(Ns...);
}();

https://godbolt.org/z/ExT674a9a

template <auto N>
constexpr auto enum_value = [] {
    if constexpr (std::is_enum_v<decltype(N)>) {
        return std::to_underlying(N);
    } else {
        return 0;
    }
};

template <auto... Ns>
constexpr auto sum_enums = (enum_value<Ns>() + ...);

https://godbolt.org/z/qMcr1Tbjr

template <auto... Ns>
constexpr auto sum_enums = (... + [] {
  if constexpr (requires { std::to_underlying(Ns); }) {
    return std::to_underlying(Ns);
  } else {
    return 0;
  }
}());

https://godbolt.org/z/rshWcE9js

template <auto N>
constexpr auto underlying_value = []{
    if constexpr(requires{std::to_underlying(N);}){
        return std::to_underlying(N);
    }
    else{
        return 0;
    }
};

template <auto... Ns>
constexpr auto sum_enums = (... + underlying_value<Ns>());

https://godbolt.org/z/KcqWqGdsG

template <auto... Ns>
constexpr auto sum_enums = (
    [](auto n) {
        if constexpr (requires { std::to_underlying(n); })
            return std::to_underlying(n);
        else
            return 0;
    }(Ns) + ...
);

https://godbolt.org/z/Pxa99q4jv

template<auto T>
[[nodiscard]] consteval auto get_enum_value() -> int {
  if constexpr (std::is_enum_v<decltype(T)> ) {
    return std::to_underlying(T);
  }
  else {
    return 0;
  }
}

template <auto... Ns>
constexpr auto sum_enums = (... + get_enum_value<Ns>());

https://godbolt.org/z/rTodjTzed

template <auto n>
constexpr auto to_value = [] {
  if constexpr (std::is_enum_v<decltype(n)>) {
    return std::to_underlying(n);
  } else {
    return 0;
  }
};

template <auto... Ns>
constexpr auto sum_enums = [] {
  return (to_value<Ns>() + ...);
}();

https://godbolt.org/z/fq13WWMEP

template <typename ...Ns>
constexpr auto sum_enums_impl(Ns... ns) {
    auto underlying_or_zero = [](auto ns) {
        if constexpr(  requires{std::to_underlying(ns); })
            return std::to_underlying(ns);
        else
            return 0;
    };
    return (  underlying_or_zero(ns) +...);
}

template <auto... Ns>
constexpr auto sum_enums = sum_enums_impl(Ns...);

https://godbolt.org/z/aoshY5Gb1

template <auto... Ns>
constexpr auto sum_enums = []{
    if constexpr (sizeof...(Ns) > 0){
        auto helper = []<auto H, auto... Hs>() {
            if constexpr (std::is_enum_v<decltype(H)>)
                 return std::to_underlying(H) + sum_enums<Hs...>;
            else
                return sum_enums<Hs...>;
        };
        return helper.template operator()<Ns...>();
    }
    else
        return 0;

}();

https://godbolt.org/z/jdcvxjf5r