2017-04-04 2 views
3

Est-il possible de déclarer un tableau const (éventuellement constexpr) en un point, puis de le définir à un autre endroit, un élément à la fois?Est-il possible de définir la valeur des éléments dans un tableau constexpr après la déclaration?

E.g.

extern constexpr int myArray[100]; 


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

Ce que j'essaye de faire aura besoin de quelque chose comme ceci. Peut-être que c'est possible en utilisant des choses comme: http://b.atch.se/posts/constexpr-counter/

Mais si cette technique va être illégale dans la prochaine norme C++ (j'espère que non) je voudrais utiliser un plus sûr.

[EDIT] Au sujet de détente des besoins .. disons que je veux faire quelque chose comme ceci:

constexpr int myConstExprFunction(int arg) { return arg + 100;} 
// other 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 est que le myConstExprFunctionEnd est capable de générer un tableau final avec les valeurs créées par les fonctions précédentes. Tout à la compilation bien sûr.

[EDIT2] 11 C++ solutions très bien accueillis

+0

Avez-vous déjà essayé cela? Quelles erreurs avez-vous eu? –

+0

@RichardCritten oui, bien sûr que j'ai essayé, mais je reçois différents types d'erreurs (.. a été précédemment déclaré ../déclaration contradictoire ... etc). La seule façon de faire quelque chose comme ça a été de manière récursive en utilisant la métaprogrammation de template – user3770392

+0

En anglais, les phrases commencent par des majuscules. –

Répondre

1

En regardant votre édition, je venais de répondre pas, parce que le compilateur ne peut pas transformer un groupe de variables dans un tableau. Ça ne marche pas comme ça. Il n'y a pas de construction en C++ qui peut prendre un tas de déclaration, les supprimer et le remplacer par une autre déclaration. Un préprocesseur ou un générateur de code source pourrait permettre la syntaxe recherchée.

Si vous êtes intéressé par une solution qui ne nécessite pas d'outillage externe, vous pouvez créer une fonction constexpr qui retourne un tableau:

constexpr auto makeMyArray() { 
    std::array<int, 100> myArray; 

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

    return myArray; 
} 

Ensuite, initialiser votre tableau:

constexpr auto myArray = makeMyArray(); 
+0

intéressant, cela semble C++ 17 droit? aucune chance de faire quelque chose comme ça en dehors d'une fonction constexpr en C++ 11? – user3770392

+1

Pas en C++ 11. Vous pouvez cependant remplacer les boucles ou les instructions multiples par un appel de fonction récursif. Cela nécessite C++ 14. Vous ne pouvez pas avoir plusieurs instructions dans une fonction constexpr en C++ 11. –

+1

Je pense que je peux utiliser l'opérateur de virgule aussi :) – user3770392

4

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

La seule façon que vous pouvez l'utiliser avec tableau est comme:

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

déclarations comme

myArray[0] = myConstexprFunction(0); 

ne peuvent être évalués au cours de l'exécution. Donc ce n'est pas possible.

+0

Je suis capable de remplir ce tableau en utilisant des techniques de métaprogrammation de gabarit, mais cela équivaut à créer un {...} – user3770392

3

Si vous voulez déclarer constexpr un tableau et initialiser sa valeur en utilisant une fonction constexpr ... le mieux que je puisse penser est d'enrouler le tableau dans un struct/array et de l'initialiser via un constructeur de délégué.

Ce qui suit est un travail à plein 14 C++ exemple

#include <utility> 
#include <iostream> 

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

template <std::size_t S> 
struct wrapArray 
{ 
    int const myWrappedArray[S]; 

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

    constexpr wrapArray() 
     : wrapArray(std::make_integer_sequence<int, S>()) 
    { } 
}; 


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 mettre en œuvre un substitut à std::integer_sequence et std::make_integer_sequence(). Ce n'est pas difficile.

+0

oui c'est similaire à ce que j'ai fait, mais ce n'est pas suffisant pour mes besoins. Je vais éditer ma question avec plus de détails – user3770392

4

L'exigence de constexpr de la récente C++ est très détendue, vous pourriez simplement écrire:

// requires C++17: 
constexpr auto myArray = [] { 
    std::array<int, 100> result {}; 
    for (size_t i = 0; i < 100; ++ i) { 
     result[i] = i * i; 
    } 
    return result; 
}(); 

Remarque je std::array<int, 100> au lieu de int[100] parce qu'une fonction ne peut pas retourner un tableau C.

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

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

numéro 1 peut être facilement travaillé autour en utilisant une fonction constexpr séparée. Problème 2 ne peut être résolu en définissant votre propre wrapper de tableau.

// requires C++14: 

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

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

constexpr auto myArray = initialize_my_array(); 
+0

toujours pas exactement ce que je cherchais mais très intéressant! avez-vous lu la deuxième partie du message (le montage)? – user3770392

+0

@ user3770392 Comment est la deuxième partie * pas * capable avec C++ 17? – kennytm

+0

Je voulais dire la deuxième partie de mon message. En passant, je peux utiliser seulement C++ 11. C++ 14 éléments comme les indices etc ok, je peux les simuler – user3770392