0

Related to this. I'd like to avoid using global variables so I resorted to using structs with enum and std::string[] (see link) in order to build menus for a small application. I would also like to have these enums in a separate header file. The selected answer in the link implies using --std=c++17, which I'd like to avoid, at least for now, and decided to use a static const std::string[] -- no need to include extra array or vector since this is initialized once, never modified, only called, ALL is always known.

As other answers on this have made it clear, I need to either initialize A::names outside the struct, or use a static const std::string& setter (see this, for example). But all the answers so far dealt with a std::string, not an array, std::string[].

This is a simple example of what I tried. It simply tries to print the contents of A::names using a for() loop iterating through the enum in struct A:

a.h:

#ifndef A_H_INCLUDED
#define A_H_INCLUDED

#include <string>

struct A
{
    enum E { ONE, TWO, ALL };
    static const std::string names[ALL];
};
#endif // A_H_INCLUDED

a.cpp:

#include "a.h"

static const std::string A::names[A::ALL] { "one", "two" };

main.cpp:

#include "a.h"
#include <iostream>

int main()
{
    for(int i=A::ONE; i<A::ALL; ++i)
        std::cout << A::names[i] << '\n';
    return 0;
}

The error after g++ main.cpp is:

main.cpp:(.text+0x24): undefined reference to `A::names[abi:cxx11]'
collect2: error: ld returned 1 exit status

Seeing the cxx11, I thought g++ --std=c++11 main.cpp would solve it, but it doesn't.

So, what am I doing wrong, or, how could I adapt the version with the setter to return an array, std::string[]? My goal is to have an alternative to a global variable, that has only one instance in memory no matter how many calls.


Here's an adapted code, from a small program, on how I would build a menu using struct with enum and string (menu_design = new QMenu... and menuDesignAction() is the function that updates):

for(unsigned char i=0; i<A::ALL; ++i)    // needs initializing
{
    QAction *tmpAction {new QAction(tr(A::names[i].c_str()))};
    tmpAction->setObjectName(QString("%1").arg(i));
    connect(tmpAction, SIGNAL(triggered(bool)), this, SLOT(menuDesignAction()));
    menu_design->addAction(tmpAction);
}

As a side-note, in the snippet above, I have to use .c_str(), but I am using a std::string in the enum. If I could make it *char[] instead of std::string[], would I avoid extra calls? If I am not wrong, how could the answers to my problem (assuming there are) be adapted so as to be able to fit somehow in the Qt snippet?

a concerned citizen
  • 787
  • 2
  • 9
  • 25

0 Answers0