[C++] constexpr Funktion => Arraygrösse in Klasse

#4068389
Lesenswert?

Hallo zusammen

Ich habe folgendes Minimalbeispiel erstellt:
1
#include <array>
2
#include <cstddef>
3

4
static constexpr std::size_t SizeA() noexcept {return 128;}
5

6
class myclass{
7
  public:
8
    static constexpr std::size_t SizeB() noexcept {return 128;}
9
  private:
10
    std::array<int, SizeA()> FieldA_; // kompiliert
11
    std::array<int, SizeB()> FieldB_; // kompiliert nicht
12
      // error: ‘static constexpr std::size_t myclass::SizeB()’ called in a constant expression
13
      // note: in template argument for type ‘unsigned int’
14
};
15

16
int main(){
17
  std::array<int, SizeA()> FieldA;          // kompiliert
18
  std::array<int, myclass::SizeB()> FieldB; // kompiliert
19
  
20
  return 0;
21
}

Das Problem ist nun, dass ich genau das machen will, das scheinbar nicht 
möglich ist. Warum ist das so und was sind gute Alternativen?

Ich könnte auch direkt
1
std::array<int, 128>
schreiben, jedoch benötige ich den Wert an mehreren Orten und möchte 
genau das vermeiden.

Compiler: GCC 4.8.2
Sprache:  C++11

Vielen Dank für eure Hilfe!
Gast #4068437
Lesenswert?

Aus dem C++ Standard:

A class is considered a completely-defined object type at the closing } 
of the class-specifier. Within the class member-specification, the class 
is regarded as complete within function bodies, [...] Otherwise it is 
regarded as incomplete within its own class member-specification.

Das heißt es wird erst der Inhalt deiner Klasse ausgewertet, und dann 
erst der Body von SizeB. Aber dann ist es schon zu spät, denn die Größe 
von FieldB_ muss dann schon bekannt sein. Umgekehrt würde es also 
funktionieren, d.h. aus dem Body von SizeB auf FieldB_ zuzugreifen.

Du könntest aus SizeB eine statische member-Variable machen oder eine 
globale Funktion.
Gast #4069428
Lesenswert?

Leo B. schrieb:
> Ich gebe zu, ich sehe solch ein Konstrukt zum ersten mal, aber gibt es
> hierfür nicht das gute alte #define?
> Nur weil das alt ist, ist es ja nicht schlecht?!
Präprozessor-Makros haben diverse Nachteile, aber leider werden sie 
immernoch unnötigerweise oft für Dinge wie Integer-Konstanten verwendet.

Makros sind eine dumme Textersetzung, die subtilere Dinge der Sprache 
wie Typen und Scopes völlig außer Acht lässt. Hat man einmal ein Makro 
definiert, kann man diesen Namen nie wieder im Projekt verwenden, auch 
nicht in inneren Scopes wie Funktionen. Macht man es versehentlich doch, 
weil man den Überblich über alle seine Macros sowie die aller 
eingebundener Libraries nicht hat, gibt es skurrile Fehlermeldungen. 
Verwendet man Konstanten oder wie hier eine Funktion, passiert das 
nicht. Außerdem haben Konstanten/Funktionen immer einen Typ; eine 
Konstante die ein "int" zurückgibt kann nie versehentlich einem "char*" 
zugewiesen werden. Ein Makro mit dem Wert 0 schon. Bei 
Funktionsoverloads oder Templates denen eine Konstante übergeben wird 
ist der Typ immer klar; bei Makros passiert es leicht dass der falsche 
verwendet wird.

In diesem Kontext hier hat die constexpr-Funktion noch einen anderen 
Vorteil: Man kann damit (rekursiv) Algorithmen schreiben, die vom 
Compiler berechnet werden, um die tatsächliche Zahl zu berechnen. Mit 
Makros geht das nicht.

Da C++ im Gegensatz zu C richtige Konstanten hat, kann man hier zur 
Definition von Zahlen komplett auf Makros verzichten und sollte es aus 
o.g. Gründen auch.
In C sind die meisten Compiler (wie GCC) auch schlau genug "static 
const" Variablen wegzuoptimieren, wenn man sie zur Definition von 
Konstanten verwendet, und daher kann (und sollte) sie hier auch 
verwenden.
#4069518
Lesenswert?

Dr. Sommer schrieb:
> Man kann damit (rekursiv) Algorithmen schreiben, die vom Compiler
> berechnet werden, um die tatsächliche Zahl zu berechnen.

Ein ergänzender Hinweis: constexpr funktionen müssen nur dann zur 
compiletime berechnet werden, wenn dessen Rückgabewert einer constexpr 
variable zugewiesen, oder als Constant Expression verwendet wird.

PS: Kennt jemand eine Anleitung wie man gcc 5.0 auf kubuntu installiert? 
Ich will c++14 features ausprobieren.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren