2 votes

(VS2015) Tentative de remplir une carte statique avec des données à partir d'une liste d'initialisation

Je possède une classe un peu comme :

class Object {
public:
    struct Flag {
        const uint32_t bit = 0;
        const wchar_t* name = L"";
        const wchar_t sign = L"";
    }

    static std::map Flags;
}

Je suis actuellement sur VS2015, mais je veux prendre en charge clang et gcc (les derniers). Mon problème est que je ne parviens pas à comprendre comment initialiser réellement cette carte avec des données.

J'ai essayé de le mettre en ligne, comme ceci :

static std::map Flags = {
    { "FOO1",       { 0, L"FOO1",       L'A' } },
    { "FOO2",       { 1, L"FOO3",       L'B' } },
    { "FOO3",       { 2, L"FOO3",       L'C' } }
}

Mais ça m'a signalé que seuls les types intégraux constants peuvent être dans la classe. D'accord ! J'ai donc laissé la déclaration dans la définition de la classe (comme indiqué dans le premier extrait de code), et j'ai mis ceci dans le cpp associé :

static std::map Object::Flags = {
    { "FOO1",       { 0, L"FOO1",       L'A' } },
    { "FOO2",       { 1, L"FOO3",       L'B' } },
    { "FOO3",       { 2, L"FOO3",       L'C' } }
}

Maintenant cela signale que :

error C2440: 'initializing': cannot convert from 'initializer list' to 'std::map,std::allocator>>'

Le truc, c'est que j'aurais juré que j'avais déjà réussi à le faire fonctionner, donc je pense que je dois avoir la syntaxe incorrecte. Si ce n'est pas le cas, clairement je ne comprends pas comment charger une carte statique dans le namespace d'une classe.

6voto

R Sahu Points 24027

Vous ne pouvez pas initialiser un objet de Object::Flag en utilisant la syntaxe d'initialisation par liste, { 0, L"FOO1", L'A' } car il a des initialiseurs de membres par défaut. Voir http://en.cppreference.com/w/cpp/language/list_initialization pour plus de détails.

Vous ne pouvez pas utiliser une initialisation d'agrégat de la forme

Object::Flag f = { 0, L"FOO1", L'A'};

pour la même raison. Voir http://en.cppreference.com/w/cpp/language/aggregate_initialization.

Changez Object::Flag pour la forme plus simple de:

struct Flag {
    const uint32_t bit;
    const wchar_t* name;
    const wchar_t sign;
};

et ensuite vous devriez pouvoir utiliser:

std::map Object::Flags = {
   { "FOO1", { 0, L"FOO1", L'A' } },
   { "FOO2", { 1, L"FOO3", L'B' } },
   { "FOO3", { 2, L"FOO3", L'C' } }};

Après ça, vous devriez également pouvoir utiliser:

Object::Flag f = { 0, L"FOO1", L'A'};

3voto

Praetorian Points 47122

Selon la norme C++11, Flag n'est pas un agrégat en raison de la présence des initialisateurs brace-or-equal (alias initialisateurs par défaut de membres), donc toute tentative d'initialisation d'agrégat pour l'initialiser échoue. C++14 a supprimé cette restriction, donc Flag est considéré comme un agrégat selon cette version de la norme, et votre code est valide.

Voici une version beaucoup plus simple de votre exemple qui ne parvient pas à se compiler avec -std=c++11, mais se compile avec succès avec -std=c++14.

#include 

struct Flag {
    const uint32_t bit = 0;
    const wchar_t* name = L"";
    const wchar_t sign = L' ';
};

int main()
{
    Flag f{ 0U, L"FOO1", L'A' };
}

Démo en direct.

VS2015 a toujours le comportement C++11, donc vos options sont soit de supprimer les initialisateurs par défaut des membres (rendant ainsi Flag un agrégat), soit de fournir un constructeur pour Object::Flag.

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