2015-04-11 10 views
5

Desidero un array statico in una funzione basata su modelli la cui lunghezza dipende dal tipo con cui la funzione è specializzata. Il mio primo tentativo è stato:Costante dipendente dal tipo nella funzione template

intestazione: file di

template<typename T> 
struct Length { 
    const static size_t len; 
}; 

template<typename T> 
void func(){ 
    static T vars[Length<T>::len]; // len not const. according to compiler! 
    // ... 
} 

Fonte:

template<> const size_t Length<double>::len = 2; 
template<> const size_t Length<float>::len = 1; 
// ... 

Tuttavia, g++ non compilare questo e si lamenta

error: storage size of ‘vars’ isn’t constant

Quindi, qual è esattamente la problema qui? So che la dimensione di un array a lunghezza fissa deve essere costante e conosciuta in fase di compilazione, ma sembra che sia il caso qui. Quando scrivo

const size_t len = 2; 

void func(){ 
    static double vars[len]; 
} 

compila senza problemi.

Domanda:

Cosa c'è di sbagliato con il codice e quali alternative ci sono per ottenere il comportamento desiderato? Non desidero allocare la memoria durante l'esecuzione ...

risposta

5

Per una variabile const da considerare una costante di compilazione (formalmente, una costante espressione), il suo valore deve essere disponibile al momento dell'utilizzo. Il che significa che le definizioni specializzate dovrebbero andare nel file di intestazione.

Se fatto come solo specializzazioni del membro, come hai fatto, credo che ti darebbe un errore di definizione multipla. Si dovrebbe andare bene con specializzata l'intero modello di classe, e mantenendo la definizione membro in linea statica:

template<typename T> 
struct Length; 

template <> 
struct Length<double> 
{ 
    static const size_t len = 2; 
}; 

Come nota a margine, il programma era in origine non valida: una specializzazione esplicita deve essere dichiarata prima dell'uso. Il che significa che devi almeno dichiarare la specializzazione di len nell'intestazione (o ovunque tu voglia utilizzarlo).

+0

Il modello di specializzazione del modello di classe è chiamato metafunction. Sicuramente la soluzione giusta qui. – Potatoswatter

+0

Non è necessario che una specializzazione esplicita di un membro sia dichiarata in precedenza. Corrisponde alla dichiarazione membro del relativo modello di classe contenente. – Potatoswatter

+0

@Potatoswatter Non penso che sia una metafunzione. Come per [Boost.MPL] (http://www.boost.org/doc/libs/1_57_0/libs/mpl/doc/refmanual/metafunction.html), "metafunction * * è una classe o un modello di classe che rappresenta una funzione invocabile in fase di compilazione. " – Angew

1

Il seguente codice compila bene per me con g++ 4.6.3 e produce l'uscita

2 
1 

array.cpp:

#include <cstddef> 
#include <iostream> 

template<typename T> 
struct Length { 
    const static size_t len; 
}; 

template<typename T> 
void func(){ 
    static T vars[Length<T>::len]; 
    std::cout << (sizeof(vars)/sizeof(*vars)) << std::endl; 
} 

template<> const size_t Length<double>::len = 2; 
template<> const size_t Length<float>::len = 1; 

int main(){ 
    func<double>(); 
    func<float>(); 
} 
$ make array 
g++  array.cpp -o array 
$ ./array 
2 
1 
Problemi correlati