How do I populate values of a static QMap in C++ Qt?

I have this in my C++ header file:

#include <QMap>
#include <QString>

class LogEvent {

public:
    LogEvent();

    enum column_t {TIMESTAMP_COLUMN = 0, TYPE_COLUMN = 1, EVENT_COLUMN = 2,
        FILE_COLUMN = 3};
    static QMap<column_t, QString> COLUMN_NAMES;

    static QMap<column_t, QString> getColumnNames() {
        return LogEvent::COLUMN_NAMES;
    }

    //blah blah blah other functions
};

This is my C++ source file:

#include "LogEvent.h"

LogEvent::LogEvent()
{
    //constructor code
}

//blah blah blah other functions

I want to add values to my static QMap COLUMN_NAMES. Where and how would I do this?

Answers


You can use static function that returns initialized map:

// source file:
QMap<column_t, QString> LogEvent::initColumnNames() {
    QMap<column_t, QString> map;
    map.insert(LogEvent::TIMESTAMP_COLUMN,"Timestamp");
    // and so on
    return map;
}

QMap<column_t, QString> LogEvent::COLUMN_NAMES = initColumnNames();

Also, in case you want to use strings internationalization in static variables and need to call QTextCodec::setCodecForTr first, it is a good idea to move static variable into its getter function:

class LogEvent {

public:
// ...
    static QMap<column_t, QString> initColumnNames();

    static QMap<column_t, QString> getColumnNames() {
        static QMap<column_t, QString> COLUMN_NAMES = initColumnNames();
        return COLUMN_NAMES;
    }
}

This way COLUMN_NAMES will be initialized with the first call of getColumnNames() and you can set the text codec beforehand. But this is not thread-safe.


In the meantime, Qt 5.2 added support for C++11 initializer lists in QMap:

QMap::​QMap(std::initializer_list<std::pair<Key, T> > list)

This means you can initialize your map like this:

static QMap<QString, int> my_map{{"a", 1}, {"b", 2}, {"c", 3}};

Another approach using an initializer list.

QMap<QString, QString> qmap_(std::map<QString, QString> {{ "", "" }});

This works for older Qt before Qt was fixed to work with initializer lists directly.


You can create std::map and use it to init QMap, or just replace QMap with std::map:

 static const std::pair<T1, T2> arr[] = { 
     std::pair<T1, T2>(v1, v2),
     std::pair<T1, T2>(v3, v4),
};

static std::map<T1, T2> my_map(arr, arr + sizeof(arr) / sizeof(arr[0]));
QMap<column_t, QString> LogEvent::COLUMN_NAMES(my_map);

Another way is init COLUMN_NAMES in constructor:

LogEvent::LogEvent() {
   if (COLUMN_NAMES.isEmpty())
     ;//init it here

but this is not thread safe, the first one method was called before main, while the second during may be called during runtime.


Need Your Help

TempData won't destroy after second request

asp.net-mvc asp.net-mvc-3 tempdata

I'm putting a value into TempData on first request in an actionfilter.

Using global variables between files?

python share globals

I'm bit confused about how the global variables work. I have a large project, with around 50 files, and I need to define global variables for all those files.