0

Myfile.h:

namespace PredicateData {

using PredicateCallable = std::function<bool(char)>;

static enum class PredicateType {
    LOWER_CASE_ALPHABET = 2147483648,
    UPPER_CASE_ALPHABET = 1073741824,
    NUMBER = 536870912,
    SPACE = 268435456,
    SENTENCE_PUNCTUATION = 134217728,
    SPECIAL_CHARACTER = 67108864
};

using PredicateMap = std::unordered_map<PredicateType, PredicateCallable>;
static PredicateMap predicatemap;

static PredicateMap _InitPredicates() {
    PredicateMap tmp;
    //do something to tmp
    return tmp;
}

}

Myfile.cpp:

PredicateData::PredicateMap PredicateData::predicatemap = _InitPredicates();

For some reason I get a compiler error: 'PredicateData::predicatemap': redefinition; multiple initialization

What am I doing wrong?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
expl0it3r
  • 325
  • 1
  • 7
  • @DanielLangr What do you mean? Then how do I initialise it? – expl0it3r Aug 17 '20 at 12:29
  • 3
    Does this answer your question? [static and extern global variables in C and C++](https://stackoverflow.com/questions/11055802/static-and-extern-global-variables-in-c-and-c) – Jan Schultke Aug 17 '20 at 12:40

2 Answers2

1

You should change static to extern in

static PredicateMap predicatemap;

It indicates to only declare the variable and tell the compiler it can find the definition in one of the compile units (possibly another one) which is "Myfile.cpp".

It becomes

extern PredicateMap predicatemap;

static keyword is used to limit the visibility of a class/function/variable/... to the current compile unit only. This has no use in a header file which is meant for sharing declarations across your project. You should remove use of static keyword in your header. It is probably not doing what you expect.

Nicolas Dusart
  • 1,867
  • 18
  • 26
0

You seem to be confusing your PrecicateData namespace with a class. For the latter, you would declare a static member in the header and then (most likely) actually define it elsewhere (for example, in "MyFile.cpp"). However, for a namespace, data and functions are declared/defined in much the same way as for 'free' global variables.

So, either add the definition of your predicatemap in the header, like this (you will, of course, need to place it after the definition of _InitPredicates):

namespace PredicateData {
    using PredicateCallable = std::function<bool(char)>;
    enum class PredicateType {
        LOWER_CASE_ALPHABET = 2147483648,
        UPPER_CASE_ALPHABET = 1073741824,
        NUMBER = 536870912,
        SPACE = 268435456,
        SENTENCE_PUNCTUATION = 134217728,
        SPECIAL_CHARACTER = 67108864
    };
    using PredicateMap = std::unordered_map<PredicateType, PredicateCallable>;
    static PredicateMap _InitPredicates()
    {
        PredicateMap tmp;
        //do something to tmp
        return tmp;
    }
    static PredicateMap predicatemap = _InitPredicates();
}

Or, alternatively, declare predicatemap as extern:

namespace PredicateData {
    using PredicateCallable = std::function<bool(char)>;
    enum class PredicateType {
        LOWER_CASE_ALPHABET = 2147483648,
        UPPER_CASE_ALPHABET = 1073741824,
        NUMBER = 536870912,
        SPACE = 268435456,
        SENTENCE_PUNCTUATION = 134217728,
        SPECIAL_CHARACTER = 67108864
    };
    using PredicateMap = std::unordered_map<PredicateType, PredicateCallable>;
    extern PredicateMap predicatemap;
    static PredicateMap _InitPredicates()
    {
        PredicateMap tmp;
        //do something to tmp
        return tmp;
    }
}

and then provide the definition in your source file (but note, you will also need to add the PredicateData:: namespace to the _InitPredicates() function):

PredicateData::PredicateMap PredicateData::predicatemap = PredicateData::_InitPredicates();

Also note that the use of static before enum class is not permitted (I have removed it in the code samples above).

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83