Originariamente inviato da RooccoXXI
Interessante possibilità, ma in questo caso mi sembra davvero restrittiva. Questo perché se un eventuale utilizzatore (sempre io!xD) creasse una classe per rappresentare l'insieme numerico dei numeri razionali in forma esatta (frazionaria), dovrebbe poter utilizzare comunque la mia classe! . Ma se potesse, in qualche modo, specificare che la sua classe é un tipo aritmetico allora tutto cambia... Questa funzione viene invocata ad ogni invocazione del costruttore anche se si trova fuori da esso? E provoca un uscita forzata del programma nel caso std::is_arithmetic<T>::value é false?
La condizione dello static_assert può essere composta, pertanto basta creare un traits per la classe che ti interessa controllare e sei a posto. Al di la di questo, static_assert è controllato in fase di compilazione e se la condizione non è superata, il compilatore mostra il messaggio in output. In questo modo non puoi compilare se il tipo che gli passi non supera la condizione (per esempio se istanzi Matrix con un tipo non aritmetico come double*).

Qui, sinceramente, mi sono perso... Significa che se nel Makefile includo Matrix.h in due diversi main() e utilizzo la stessa specializzazione del template il compilatore si lamenta? Quindi tutte le funzioni inline?
Se hai un main.cpp e altrofile.cpp entrambi che includono Matrix.h, il linker si lamenta perché trova le stesse funzioni in due diversi file .cpp e non sa chi richiamare. L'inline serve a toglierlo dall'imbarazzo.

Mi sembrava più matematico. Nei miei libri di fisica computazionale e analisi numerica spesso gli algoritmi partono da 1, perché lo 0 é l'indice delle condizioni ai limiti e non necessita di essere salvato nella matrice (perché la condizione al limite rimane prevalentemente invariata)...
E' solo una notazione. Quello che in matematica va da 1 a n, con limite 0, in C++ va da 0 a n-1 con limite -1 (visto che gli indici non possono essere negativi). Dopo un po' la traslazione viene automatica. Comunque tratta la cosa come più ti è congeniale, non è certo questo il problema.

Quindi l'istruzione di accesso [i] é praticamente identica a [i-1] (nel senso che l'operazione i-1 non é rilevante)?
Beh, ci impieghera un picosecondo in più, che in quelche migliaio di anni può farsi sentire.

Intendi che si può allocare memoria anche con istruzioni diverse da new e delete (più performanti)? Comunque se dici che passare da T* all'allocatore standard in un secondo momento (cosa comporta il passaggio?) non é difficile, credo di rimanere sul T*, più comprensibile (per il mio livello).
E' un modo diverso e più flessibile di gestire la politica di allocazione della memoria.
All'interno dell'allocatore puoi decidere se usare new, malloc, altre funzioni di terze parti per la gestione dell'heap, usare una funzione per un numero prestabilito di elementi.
L'argomento è vasto e come ho detto si può affrontare in seguito (se ti interessa).