Ho riflettuto su una domanda di base su in che misura imporre l'invarianza di una classe . Forse è formulato male, così come un esempio, diciamo che voglio scrivere una classe che memorizza una gamma limitata di colori. Il costruttore della classe dovrebbe prendere le dimensioni della tavolozza - l'idea è che puoi aggiungere tutti i colori alla tavolozza che vuoi, ma limita la dimensione su una politica FIFO. Quindi diremo che voglio limitare arbitrariamente questa dimensione all'intervallo da 1 a 32 ("nessuno avrà mai bisogno di più di 32 colori").
Iniziamo ...
class palette
{
public:
palette(unsigned int max_size) : m_max_size{max_size} { }
private:
unsigned int m_max_size;
};
Finora, tutto bene. Tranne che non sto facendo nulla per confermare che la dimensione massima rientri nel mio intervallo ristretto, cioè l'invariante può essere rotto direttamente dalla costruzione.
(Giusto per chiarire: questa classe non è intesa per l'uso in alcune librerie pubbliche - è semplicemente una classe interna a una singola applicazione)
Ti vengono in mente quattro opzioni oltre "non fare nulla":
-
Inserisci un commento sulla classe per chiedere ai chiamanti di usare correttamente la classe.
// Please only call with 1 <= max_size <= 32
-
Asserisci che si trova nel raggio d'azione.
assert(max_size >= 1 && max_size <= 32);
-
Genera un'eccezione se è al di fuori dell'intervallo
if (max_size < 1 || max_size > 32) throw std::invalid_argument();
-
Verifica il compilatore convertendolo in un modello
template <unsigned int MAX> class palette { public: palette() { // no need for the argument any more static_assert(MAX >= 1 && MAX <= 32, "oops"); } };
Le opzioni n. 1 sembrano un po 'come un pio desiderio, ma forse è abbastanza buono per "solo" una classe interna? Le opzioni dalla 2 alla 4 sono sempre più esigenti riguardo alle dimensioni, al punto che la # 4 modifica la sintassi in modo che il compilatore riporti un errore se la classe non viene utilizzata correttamente.
Gradirei qualsiasi pensiero su questo. Capisco che la risposta inizierà probabilmente con "Beh tutto dipende ...", ma sto solo cercando alcune linee guida generali o alcuni suggerimenti alternativi.