or
Jonathan Mee
I want to use [`std::underlying_type`](https://en.cppreference.com/w/cpp/types/underlying_type) with [`std::enable_if`](https://en.cppreference.com/w/cpp/types/enable_if) to conditionally cause [Substitution Failure Is Not An Error (SFINAE)](https://en.cppreference.com/w/cpp/language/sfinae). I'm using this function to conditionally allow either `unsigned int` parameters or enum parameters whose underlying type is `uint8_t`:

    template <typename T>
    std::enable_if_t<(std::is_enum_v<T> && std::is_same_v<std::underlying_type_t<T>, uint8_t>) || std::is_same_v<T, unsigned int>> Foo(const T param) {
        std::cout << static_cast<int>(param) << std::endl;
    }

However I'm getting the error when calling `Foo(13U)`:

> error: no matching function for call to `Foo(unsigned int)`

How can I change the `std::enable_if_t` parameter to make this work as intended?

[**Live Example**](http://coliru.stacked-crooked.com/a/ef210af489da6d12)
Top Answer
Jonathan Mee
The problem here is the [`std::underlying_type`](https://en.cppreference.com/w/cpp/types/underlying_type) struct template parameter must be an enumeration type:

> Otherwise, if `T` is not an enumeration type, there is no member `type`

This means calling `std::underlying_type_t<int>` is a compilation error. Short circuiting logical-and operators does not prevent template evaluation. To avoid this we'll need 2 things:

 1. [`std::conditional`](https://en.cppreference.com/w/cpp/types/conditional) to optionally use `underlying_type`
 1. And an alternative structure which has a `type` member which could be returned instead, I've chosen `template<typename... Ts> struct make_void { typedef void type; }` from https://en.cppreference.com/w/cpp/types/void_t


Using these 2 `Foo` can be written so that the `type` member of `std::underlying_type` is only accessed if `std::is_enum` is valid:

    template <typename T>
    std::enable_if_t<std::is_same_v<typename std::conditional_t<std::is_enum_v<T>, std::underlying_type<T>, decltype(make_void<T>())>::type, uint8_t> || std::is_same_v<T, unsigned int>> Foo(const T param) {
        std::cout << static_cast<int>(param) << std::endl;
    }

[**Live Example**](http://coliru.stacked-crooked.com/a/88f31ccbf8914208)
How can I conditionally use std::underlying_type?

This is a dedicated room for discussion about this question.

Once logged in you can direct comments to the question poster (or any answer poster) here.