Originariamente inviato da shodan
Il che non impedisce al compilatore di istanziare il template con tutto il possibile.
Se vuoi restringere il range dei tipi con cui la classe può essere istanziata, devi usare static_assert:
Es.
codice:
#include <type_traits>
template <typename T>
class Matrix {
    // solo i tipi aritmetici possono istanziare la classe.
    static_assert(std::is_arithmetic<T>::value,"Matrix funziona solo con tipi di dato aritmetico. Es. char, int, double");
    etc...
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?

Niente di tutto questo. Semplicemente se includi il file in due diverse unità di compilazione il linker si lamenta perché hai violato la "one definition rule", cioè un unico punto di accesso per ogni singola specializzazione del template.
Di questi tempi è solo il compilatore che decide cosa mettere inline e cosa no, anche se glielo dici (a meno di direttive specifiche di ogni compilatore).
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?

Cosa intendi per efficienza?
Se intendi l'accesso al singolo elemento, il tempo è lo stesso.
Se intendi: creazione in un colpo solo della matrice al posto di un doppio for, copia di ogni singolo elemento tramite memcpy() al posto di due cicli for, confrontare l'uguaglianza di due istanze di matrice (di pari righe e colonne) con un solo for al posto di due (o addirittura con memcmp()), direi di si.
Effettivamente la diminuzione dei cicli for é un gran guadagno!

Non mi pare un gran cosa far abbaiare un gatto. Usa gli indici in maniera normale senza complicarti la vita per niente. E comunque sono interi, l'efficienza è la stessa.
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)...

Quindi l'istruzione di accesso [i] é praticamente identica a [i-1] (nel senso che l'operazione i-1 non é rilevante)?

Nella STL l'allocatore serve per cambiare il modo di fornire memoria alla struttura dati sottostante e svincolarla dall'accoppiata new/delete. Questo perché se il programmatore dedide di usare un allocatore più performate di quello standard, può farlo (allocare memoria è un'operazione pesante nel lungo periodo ed è questo motivo per cui ti ho suggerito di usare un T* al posto di un T**. Nel primo caso fai un'unica allocazione, nel secondo fai colonne + 1 allocazioni e questo comporta meno efficienza in fase di allocazione e deallocazione del puntatore). Le funzioni chiave sono: allocate() e deallocate().
Per l'uso dai un'occhiata qui.
http://www.codeproject.com/Articles/...-and-Implement
In ogni caso è solo un'idea che si può applicare in seguito (ed eventualmente vedere perché è conveniente in certi casi).
Questo sarebbe un argomento da approfondire, ma credo che ci voglia un po' di tempo! . Intendi che si può allocare memoria anche con istruzioni diverse da new e delete (più performanti)? Mi leggerò la pagina che hai linkato. 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).

Grazie,
R.