Я бы сказал, что прямым решением этого вопроса может быть следующее:
template< typename T, T X, T L, T H>
using inside_t =
std::enable_if_t< (X <= H) && (X >= L),
std::integral_constant<T, X> >;
Применительно к ОП:
template<typename C, unsigned K> struct X; // final {};
template<unsigned K>
struct X<char, K> final
{
using ascii_ordinal = inside_t<unsigned, K, 0, 127>;
char value = char(ascii_ordinal::value);
};
Который выдает действительно ужасные сообщения об ошибках CL, когда выполняет свою работу:
X<char, 300> a; //here 300 is out of range and I would like to be able to detect that.
Хотя гораздо менее привлекательный, но наиболее удобный API может быть:
template<unsigned K>
struct X<char, K> final
{
static_assert( K >= 0U && K <= 127U, "\n\nTeribly sorry, but value must be between 0 and 127 inclusive\n\n") ;
char value = char(K);
};