array.size() als Template-Parameter
-
Hallo, ich habe folgenden Code:
#include <bitset> #include <array> #include <iostream> template<size_t N> void func(const std::array<bool,N>& arr) { std::bitset<arr.size()> bits(0); for(size_t i=0; i<N; ++i) bits[i] = arr[i]; std::cout << bits << std::endl; } int main() { std::array<bool,15> myarray = {true, false, false, false, true, true, false}; func(myarray); }
Dieser kompiliert problemlos mit dem GNU Compiler. Der Microsoft Compiler in Visual Studio 2015 und Clang++ beschweren sich jedoch beide über Zeile 8. Das Template-Argument arr.size() sei keine Compiletime-constant-expression (constexpr).
Hier steht jedoch das Gegenteil:
http://www.cplusplus.com/reference/array/array/size/Wer hat Recht?
-
Beklagen hilft nicht Ein workaround schon eher:
#include <bitset> #include <array> #include <iostream> template < class T > struct size_from_array; template < typename T, std::size_t N > struct size_from_array< std::array<T,N> > { enum { size = N }; }; template < std::size_t N > void func(const std::array<bool,N>& arr) { std::bitset< size_from_array< std::array<bool,N> >::size > bits(0); for(size_t i=0; i<N; ++i) bits[i] = arr[i]; std::cout << bits << std::endl; } int main() { std::array<bool,15> myarray = {true, false, false, false, true, true, false}; func(myarray); }
mfg Torsten
-
Eine ähnliche Frage habe ich schonmal beantwortet: http://stackoverflow.com/a/36432725/3647361
Hier hat GCC Recht, da
size
alsconstexpr
deklariert ist und einfach eine Konstante zurückgibt - ob das Objekt Argument überhauptconst
ist, ist irrelevant, da es innerhalb der Funktion nicht verwendet wird.
Das hängt aber natürlich davon ab, wie aktuell deine Implementierungen alle sind: Clang trunk kompiliert deinen Code.
-
Hallo, kreativer Workaround. Mich würde aber trotzdem interessieren, ob der Fehler tatsächlich beim Compiler oder bei mir liegt. Ich bin vorsichtig geworden Compiler zu beschuldigen, da sie erfahrungsgemäß tatsächlich fast immer richtig liegen.
-
Naja, wenn wir mal davon ausgehen, dass die angegebene Referenz korrekt ist, dann kommt es drauf an, ob das Beispiel C++11 oder C++14 ist. Für C++14 wäre Dein code dann korrekt. Nur, was nützt es Dir, wenn der Code korrekt ist?
-
@Arcoth: Danke für die klare Einschätzung. Hier läuft noch Clang 3.7.1, da ist der Bug wohl noch drin, der in 3.9.0 gefixt ist. Wieder ein Grund mehr auf den Microsoft Compiler einzuprügeln (Bitte nicht zu ernst nehmen)
-
Torsten Robitzki schrieb:
Beklagen hilft nicht Ein workaround schon eher:
#include <bitset> #include <array> #include <iostream> template < class T > struct size_from_array; template < typename T, std::size_t N > struct size_from_array< std::array<T,N> > { enum { size = N }; }; template < std::size_t N > void func(const std::array<bool,N>& arr) { std::bitset< size_from_array< std::array<bool,N> >::size > bits(0); for(size_t i=0; i<N; ++i) bits[i] = arr[i]; std::cout << bits << std::endl; } int main() { std::array<bool,15> myarray = {true, false, false, false, true, true, false}; func(myarray); }
mfg Torsten
Ja..... oder man benutzt einfach
N
.
-
Torsten Robitzki schrieb:
Naja, wenn wir mal davon ausgehen, dass die angegebene Referenz korrekt ist, dann kommt es drauf an, ob das Beispiel C++11 oder C++14 ist. Für C++14 wäre Dein code dann korrekt.
Warum wäre der Code für C++11 nicht korrekt? Ich habe mit -std=c++11 kompiliert.
-
Arcoth schrieb:
Ja..... oder man benutzt einfach
N
.Ähh, .... ja! Zumindest im gg. Beispiel.
-
Mr Train schrieb:
Warum wäre der Code für C++11 nicht korrekt? Ich habe mit -std=c++11 kompiliert.
Sorry, habe mich verguckt. Müsste natürlich für C++11 und C++14 funktionieren.
-
Mr Train schrieb:
Torsten Robitzki schrieb:
Naja, wenn wir mal davon ausgehen, dass die angegebene Referenz korrekt ist, dann kommt es drauf an, ob das Beispiel C++11 oder C++14 ist. Für C++14 wäre Dein code dann korrekt.
Warum wäre der Code für C++11 nicht korrekt?
Das wüsste ich auch gern, denn AFAICS ist der Code auch in C++11 korrekt (N3337 zeigt
size
alsconstexpr
).