Tutto ha un costo, anche se non viene misurato nelle prestazioni di runtime.
Codificare tali ipotesi nel sistema di tipi sembra una buona idea. Ma non è senza i suoi difetti. In particolare, richiede di avere e utilizzare una serie di tipi sempre più specifici per ipotesi sempre più specifiche.
Diciamo che hai una funzione che prende una matrice dall'utente e modifica i primi tre elementi in essa contenuti. Ora, questa funzione fa due presupposti: che in realtà c'è una matrice e che la matrice ha almeno 3 elementi lunghi.
Ci sono tipi che possono codificare entrambi questi presupposti. Il tipo di libreria di supporto delle linee guida span
può coprire entrambi. Ma guarda il codice per quel tipo. Se non fosse disponibile, probabilmente non lo scriverebbe da solo.
Più supposizioni di questo tipo hai, e più casi speciali ottengono, più difficile è scrivere un tipo solo per loro. Dopotutto, span
risolve solo questo particolare problema come un sottoprodotto parziale di risolvere il suo problema reale : avere un modo per rappresentare una matrice di alcune dimensioni.
Quindi è un atto di bilanciamento. Non vuoi passare più tempo a scrivere tipi di casi speciali, ma ne hai bisogno per coprire molte basi. Dove esattamente si disegna la linea dipende dalle proprie esigenze, ma non credo che sia utile provare a codificare tutto nel sistema di tipi.
Inoltre, avendo contratti come parte di C ++, quali persone stanno lavorando on (PDF) , sarebbe in grado di colmare il divario qui in molti dei casi speciali.
C'è anche il problema di trattare combinazioni di tali contratti. Il contratto not_null
è generalmente una buona idea, ma per sua stessa natura non può funzionare con i tipi solo di spostamento che lasciano l'oggetto spostato da null. Pertanto, not_null<unique_ptr<T>>
non è un tipo funzionale.
Ancora una volta, non è detto che non dovresti avere questi. Ma hai davvero bisogno di pensare a quando è veramente appropriato avere un tipo che incapsula un contratto e quando non lo è.