2015-04-17 4 views
14

Perché le seguenti compilato con clang ma non con g++ 4.9argomento di default per la specializzazione parziale [Clang sì, GCC no]

#include <array> 

template< typename T1, typename T2 , typename T3 = int> 
struct A; 

template<typename T, unsigned int N, typename T2, typename T3> 
struct A< std::array<T,N>, T2, T3 > { 
    int a; 
}; 

int main() 
{ 
    A< std::array<int,10>, double> a; 
    a.a +=3; 
} 

http://coliru.stacked-crooked.com/a/c7800f49ba5aac43

g ++ non trova una specializzazione adeguata e si lamenta con "incompleta genere". Mi chiedo da quando, l'argomento di default typename T3 = int dovrebbe applicarsi per la specializzazione (o non si applica solo per la piena specializzazione?)

+10

Perché stai usando 'int' senza segno invece di' std :: size_t'. Con quest'ultimo, entrambi i compilatori accettano il programma. – dyp

+1

Correlati: http://stackoverflow.com/q/21740896/ – dyp

+1

Potrebbe essere https://llvm.org/bugs/show_bug.cgi?id=16279 – dyp

risposta

4

I modelli A<T1, T2, T3> e A<T1, T2> non sono completi definiti in modo non è possibile utilizzare i vostri membri, è possibile risolvere il problema di definire questo Modelli in questo modo:

#include <array> 

template< typename T1, typename T2 , typename T3 = int> 
struct A { 
    int a; 
}; 

template<typename T, unsigned int N, typename T2, typename T3> 
struct A< std::array<T,N>, T2, T3 > { 
    int a; 
}; 

int main() 
{ 
    A< std::array<int,10>, double> a; 
    a.a +=3; 
} 

Un altro bell'esempio di specializzazione più semplice:

template<typename T, unsigned int N> 
struct A { 
    T a = N; 
}; 

template<unsigned int N> 
struct A<int, N> { 
    int a = 2*N; 
}; 

#include <iostream> 
using namespace std; 

main() { 
    A<float, 30> af; 
    A<int, 30> ai; 
    cout << af.a << endl << ai.a << endl; 
} 

Come @dys dicono del sul tuo commento utilizzando std::size_t invece unsigned int opere:

template< typename T1, typename T2 , typename T3 = int> 
struct A; 

template<typename T, std::size_t N, typename T2, typename T3> 
struct A< std::array<T,N>, T2, T3 > { 
     T3 a = N; 
     int b; 
}; 

int main() 
{ 
     A< std::array<int,10>, double> a; 
     a.a +=3; 

     A< std::array<int,10>, double, int> b; 
     b.b +=3; 
} 
+0

non penso che sia la risposta , l'asnwer dovrebbe essere il commento di @ dyp. Il problema è che corrisponde al primo prototipo (che è incompleto sì) perché la corrispondenza del template è ovviamente pedante rispetto ai tipi usati -> '' template std :: array'' – Gabriel

+0

@dyp hanno davvero ragione, usare 'std :: size_t' invece 'unsigned int' funziona bene. –