Před časem jsem si s něčím podobným hrál. Povedlo se mi to jenom částečně. Jestli ten výsledek stojí za to je těžko říct.
S kontrolou přiřazení je problém ten, že překladač udělá z literálu normální int dřív než se k němu rozumně dostaneš. Takže z toho literálu musíš udělat něco jako std::integral_constant. Asi nejrozumněji vypadající inicializace bude:
hours = lit<13>();
hours = 13_ic;
Pro druhou verzi bylo třeba si napsat vlastní uživatelsky definovaný literál. Znamená to si napsat parser intů přes šablony. IMO to za to vážně nestojí. Na první verzi stačí:
template<intmax_t I> struct lit : std::integral_constant<intmax_t, I> {};
Pak už může mít ten interval šablonový konstruktor co bere integral_constant a v něm se dá použít ten static_assert.
Co jsem nakonec dotáhl do použitelného stavu nebyly plnotučné intervaly ale jen otypované indexy a velikosti.
- Rozsahy se kontrolují assertem v runtime. Ale ve chvíli kdy se udělal z intu index, tak žádné další asserty nebyly.
- Kromě maximální velikosti měly ty indexy i tag. Takže prohození indexů jablek a hrušek se při kompilaci chytlo.
- Hlavně jsem tím vychytal automatické konverze intů. Index se dal převést na libovolný integer, ale static_assert hlídal jestli se tam vleze. A taky jsem tím zatrhl Cčkovou past kdy "( uint <= -1 ) == true"
Hlavně tyhle hrátky ber jako druh intelektuální masturbace a ne jako něco, co se od tebe čeká. Spíš se nauč pracovat s nějakým statickým analyzátorem. S ním dostaneš daleko víc muziky za míň peněz.