#include <iostream>
#include <stdexcept>
#include <type_traits>
//Concept looted from https://stackoverflow.com/a/16000226
// definitely take the time to read the answer to grok what's going on.
template <typename T, typename = int>
struct HasFirst : std::false_type { };

template <typename T>
struct HasFirst <T, decltype((void) T::First, 0)> : std::true_type { };

template <typename T, typename = int>
struct HasLast : std::false_type { };

template <typename T>
struct HasLast <T, decltype((void) T::Last, 0)> : std::true_type { };

template <class TYPE>
TYPE do_conversion(int value)
{
    static_assert(HasFirst<TYPE>::value, "Need First");
    static_assert(HasLast<TYPE>::value, "Need Last");
    if (value >= static_cast<int>(TYPE::First) &&
        value < static_cast<int>(TYPE::Last))
    {
        return static_cast<TYPE>(value);
    }
    throw std::out_of_range("Inv value");
}

enum class Weekday
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
    Last,
    First = Monday
};

void demo(int value)
{
    try
    {
        std::cout << "Day " << value << " is ";
        switch (do_conversion<Weekday>(value))
        {
            case Weekday::Monday:
                std::cout << "Monday\n";
                break;
            case Weekday::Tuesday:
                std::cout << "Tuesday\n";
                break;
            case Weekday::Wednesday:
                std::cout << "Wednesday\n";
                break;
            case Weekday::Thursday:
                std::cout << "Thursday\n";
                break;
            case Weekday::Friday:
                std::cout << "Friday\n";
                break;
            case Weekday::Saturday:
                std::cout << "Saturday\n";
                break;
            case Weekday::Sunday:
                std::cout << "Sunday\n";
                break;
            default:
                std::cout << "Huh. How did we get here?\n";
                break;
        }
    }
    catch (const std::out_of_range& ) {
        std::cout << "Invalid\n";
    }
}

int main()
{
    for (int i = -1; i < 10; i++)
    {
        demo(i);
    }
}
