4 votes

Est-il possible de définir la valeur des éléments dans un tableau constexpr après sa déclaration?

Est-il possible de déclarer un tableau const (éventuellement constexpr) à un endroit, puis de le définir à un autre endroit, un élément à la fois?

Par exemple.

extern constexpr int myArray[100];

myArray[0] = myConstexprFunction(0);
myArray[1] = myConstexprFunction(1);
// ...
myArray[100] = myConstexprFunction(100);

Ce que j'essaie de faire nécessitera quelque chose comme ça. Peut-être est-il possible d'utiliser des choses comme: http://b.atch.se/posts/constexpr-counter/

Mais si cette technique devient illégale dans la prochaine norme C++ (j'espère que non) j'aimerais en utiliser une plus sûre.

[EDIT] et si on assouplissait certaines exigences.. disons que je veux faire quelque chose comme ceci:

constexpr int myConstExprFunction(int arg) { return arg + 100;}
// autre code...
constexpr int a = myConstExprFunctionBegin(10);
constexpr int b = myConstExprFunction(20);
constexpr int c = myConstExprFunction(30);
constexpr int d = myConstExprFunctionEnd(40);

ce que je voudrais avoir, c'est que myConstExprFunctionEnd soit capable de générer un tableau final avec les valeurs créées par les fonctions précédentes. Tout cela bien sûr au moment de la compilation.

[EDIT2] Les solutions C++11 sont les bienvenues

4voto

Dante. Points 1685

constexpr déclare qu'il est possible d'évaluer la valeur de la fonction ou de la variable au moment de la compilation.

Donc, la seule façon dont vous pourriez l'utiliser avec un tableau est comme suit :

constexpr int myArray[100] = {1, 2, 3, ...};

des déclarations comme

myArray[0] = myConstexprFunction(0);

ne peuvent être évaluées qu'au moment de l'exécution. Il n'est donc pas possible de le faire.

4voto

KennyTM Points 232647

L'exigence de constexpr du récent C++ est très détendue, vous pouvez donc simplement écrire :

// nécessite C++17 :
constexpr auto myArray = [] {
    std::array result {};
    for (size_t i = 0; i < 100; ++ i) {
        result[i] = i * i;
    }
    return result;
}();

Remarquez que j'ai utilisé std::array au lieu de int[100] car une fonction ne peut pas renvoyer un tableau C.

Le code ci-dessus nécessite C++17 pour deux raisons :

  1. constexpr lambda
  2. Le mutable operator[] n'est pas constexpr avant C++17

Le problème 1 peut être facilement contourné en utilisant une fonction constexpr séparée. Le problème 2 ne peut être résolu qu'en définissant votre propre wrapper de tableau.

// nécessite C++14 :

template 
struct ConstexprArray {
    T data[n];
    constexpr ConstexprArray() : data{} {}
    constexpr T& operator[](size_t i) { return data[i]; }
};

constexpr auto initialize_my_array() -> ConstexprArray {
    ConstexprArray result {};
    for (size_t i = 0; i < 100; ++ i) {
        result[i] = i * i;
    }
    return result;
}

constexpr auto myArray = initialize_my_array();

3voto

max66 Points 4276

Si vous voulez déclarer constexpr un tableau et initialiser sa valeur en utilisant une fonction constexpr... la meilleure solution que je puisse penser est d'encapsuler le tableau dans une structure/tableau et de l'initialiser via un constructeur délégué.

Voici un exemple complet fonctionnel en C++14

#include 
#include 

constexpr int myConstexprFunction (int i)
 { return i << 1; } // retourne 2*i

template 
struct wrapArray
 {
   int const myWrappedArray[S];

   template 
   constexpr wrapArray (std::integer_sequence const &)
      : myWrappedArray { myConstexprFunction(Is)... }
    { }

   constexpr wrapArray ()
      : wrapArray(std::make_integer_sequence())
    { }
 };

int main ()
 {
   constexpr wrapArray<100>  wa100;

   for ( auto i : wa100.myWrappedArray )
      std::cout << i << ", ";

   std::cout << std::endl;
 }

Si vous avez besoin d'un code C++11, vous devez implémenter un substitut pour std::integer_sequence et pour std::make_integer_sequence(). Ce n'est pas difficile.

3voto

Guillaume Racicot Points 1106

En regardant votre édition, je répondrais simplement non, car le compilateur ne peut pas transformer un groupe de variables en un tableau. Ça ne fonctionne tout simplement pas de cette manière. Il n'y a aucune construction en C++ qui puisse prendre une série de déclarations, les supprimer et les remplacer par une autre déclaration. Un préprocesseur de code source ou un générateur pourrait permettre la syntaxe que vous recherchez.

Si vous êtes intéressé par une solution qui ne nécessite aucun outil externe, vous pouvez créer une fonction constexpr qui renvoie un tableau :

constexpr auto makeMyArray() {
    std::array myArray;

    myArray[0] = myConstExprFunction(10);
    myArray[1] = myConstExprFunction(20);
    // ...

    return myArray;
}

Ensuite, initialisez votre tableau :

constexpr auto myArray = makeMyArray();

1voto

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X