2016-04-14 14 views
16

Il seguente codice:Perché std :: array :: size constexpr con tipi semplici (int, double, ...) ma non std :: vector (GCC)?

std::array<int, 4> arr1; 
std::array<float, arr1.size()> arr2; 

... compila sia con gcc e clang perché std::array::size è considerato constexpr.

ma il seguente non viene compilato con gcc (versione 5.3.0 20.151.204):

std::array<std::vector<int>, 4> arr1; 
std::array<std::vector<double>, arr1.size()> arr2; 

Per me, non c'è ragione tale codice non dovesse compilare se il primo funziona, ma dal momento che non ho trovare un sacco di post su questo non so se si tratta di un bug gcc o di un'estensione clang?

L'errore da gcc (che io non capisco ...):

main.cpp: In function 'int main()': 
main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' 
    std::array<std::vector<double>, arr1.size()> arr2; 
              ^
In file included from main.cpp:1:0: 
/usr/local/include/c++/5.3.0/array:170:7: note: 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' is not usable as a constexpr function because: 
     size() const noexcept { return _Nm; } 
    ^
/usr/local/include/c++/5.3.0/array:170:7: error: enclosing class of constexpr non-static member function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' is not a literal type 
/usr/local/include/c++/5.3.0/array:89:12: note: 'std::array<std::vector<int>, 4ul>' is not literal because: 
    struct array 
      ^
/usr/local/include/c++/5.3.0/array:89:12: note: 'std::array<std::vector<int>, 4ul>' has a non-trivial destructor 
main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' 
    std::array<std::vector<double>, arr1.size()> arr2; 
              ^
main.cpp:6:48: note: in template argument for type 'long unsigned int' 
    std::array<std::vector<double>, arr1.size()> arr2; 
               ^
+1

È interessante notare che MSVS2015 e clang si compilano entrambi. A intellisense MSVS non piace, ma è accettato dal compilatore. – NathanOliver

+1

C'è 'tuple_size > :: value' se hai bisogno di una soluzione alternativa: / – melak47

risposta

21

credo che questo sia un relativo a CWG issue 1684. In precedenza, i requisiti constexpr inclusi:

La classe di cui una funzione constexpr è un membro deve essere di tipo letterale

E std::array<std::vector<int>, 4> è non un tipo letterale, e quindi la sua funzione size() membro non sarebbe constexpr. Tuttavia, la nuova formulazione consente le funzioni di membro non statico constexpr per i tipi non letterali, presupponendo che tali funzioni soddisfino tutti gli altri requisiti di constexpr (che fa chiaramente array<T,N>::size()).

Per la nuova formulazione, si tratta di un bug gcc. Precedentemente archiviato come 66297.