Se quello che vogliamo è: dato un parametro modello uint64_t
, dare il più piccolo tipo senza segno che è in grado di rappresentarlo, quindi quello che vogliamo veramente è solo una semplice iterazione in fase di compilazione.
namespace details {
template <typename T>
struct tag {
using type = T;
};
// base case: just fail
template <uint64_t V, typename... >
struct min_unsigned_type;
// recursive case: check using numeric_limits
template <uint64_t V, typename T, typename... Ts>
struct min_unsigned_type<V, T, Ts...>
: std::conditional_t<(V <= std::numeric_limits<T>::max()),
tag<T>,
min_unsigned_type<V, Ts...>>
{ };
}
Poi basta un alias per avvolgere le cose insieme:
template <uint64_t V>
using min_unsigned_type =
typename details::min_unsigned_type<V,
uint8_t, uint16_t, uint32_t, uint64_t>::type;
Questo ha il vantaggio di essere in grado di specificare con facilità quanto si vuole andare, o anche essere in grado di aggiungere i tipi senza segno più grandi se è qualcosa che trovi necessario.
E infine la classe:
template <uint64_t V>
struct A {
static constexpr uint64_t k_ = V;
min_unsigned_type<V> u_;
};
Se 'k' è un' uint8_t', allora cosa significa questo ?: '... = A <256, uint16_t>'. 256 è più di 'uint8_t' può contenere, quindi questo non ha senso per me –
Chi ha svalutato questa domanda ?? Non aveva senso finché non dedussi un po 'di tempo a dedurre dalle risposte ciò che la domanda stava effettivamente chiedendo. – Barry