0

I'm attempting to limit the use of this function to enum classes that have unsigned underlying types (and have AddSubtract as an enumeration) but I cannot for the life of me figure out the correct syntax.

template <class E>
concept EnumAddSubtract =
 std::is_enum_v<E> &&
 std::is_unsigned<std::underlying_type<E>::type> && //ERROR HERE
 requires() { {E::AddSubtract}; };

template <EnumAddSubtract E>
constexpr E operator+(E const & lhs, int const & rhs) {
    return static_cast<E>(static_cast<std::underlying_type<E>::type>(lhs) +
 static_cast<std::underlying_type<E>::type>(rhs));
}

I'm able to call is_unsigned on underlying_type<>::type in other contexts, such as:

enum class C : unsigned {};
std::cout << std::is_unsigned<std::underlying_type<C>::type>::value << '\n';
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
GLJeff
  • 139
  • 10
  • 1
    Please provide the minimal complete example (with all `#include`s) and full compiler's message – yeputons Jan 02 '23 at 23:28
  • 3
    a) either [`typename` before `std::underlying_type<>::type`](https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) or use `underlying_type_t`; b) `is_unsigned_v`, not `is_unsigned`; c) no parens after `requires`. – yeputons Jan 02 '23 at 23:31
  • 2
    @yeputons that should be posted as an answer rather than a comment – Remy Lebeau Jan 02 '23 at 23:31
  • @yeputons b ;) I guess `typename` for dependent types has been relaxed for C++20 – alagner Jan 02 '23 at 23:32

1 Answers1

0

I needed to take the value of is_unsigned. Using yeputons's suggestion to use helper function variants that end in _v and _t, here is code that compiles:

#include <iostream>
#include <type_traits>
 
template <class E>
concept EnumAddSubtract = std::is_enum_v<E> && std::is_unsigned_v<std::underlying_type_t<E>> && requires() { {E::AddSubtract}; };

template <EnumAddSubtract E>
constexpr E operator+(E const & lhs, int const & rhs) {
    return static_cast<E>(static_cast<std::underlying_type<E>::type>(lhs) + static_cast<std::underlying_type<E>::type>(rhs));
}

enum class C : unsigned {};
typedef std::underlying_type<C>::type tester;
 
int main() 
{
    std::cout << std::is_unsigned<std::underlying_type<C>::type>::value << '\n';
    std::cout << std::is_unsigned<tester>::value << '\n';
}
GLJeff
  • 139
  • 10