1

I'm trying to make a small unordered map that I can use to store keys and values permanently, as a sort of dictionary. The type TengwarChar is just an object with two values, a string and an enum, and later I'll add methods too. The header I use is as follows:

#ifndef TENGWARLIBRARY_H
#define TENGWARLIBRARY_H

#include "tengwarchar.h"
#include <unordered_map>
#include <algorithm>
#include <string>

typedef std::unordered_map<std::string, TengwarChar> CharMap;

extern const CharMap numbers = {
    {"0", TengwarChar("ð", SHORT)},
    {"1", TengwarChar("ñ", SHORT)},
    {"2", TengwarChar("ò", SHORT)},
    {"3", TengwarChar("ó", SHORT)},
    {"4", TengwarChar("ô", SHORT)},
    {"5", TengwarChar("õ", SHORT)},
    {"6", TengwarChar("ö", SHORT)},
    {"7", TengwarChar("÷", SHORT)},
    {"8", TengwarChar("ø", SHORT)},
    {"9", TengwarChar("ù", SHORT)}
 };

std::string translateFromEnglishToTengwar(std::string str);
std::string translateFromTengwarToEnglish(std::string str);

#endif // TENGWARLIBRARY_H

Then, I have a simple testing cpp file that goes along with it:

#include "tengwarlibrary.h"

std::string translateFromEnglishToTengwar(std::string str)
{
    std::transform(str.begin(), str.end(), str.begin(), (int (*)(int))std::tolower);
    return str;
}

std::string translateFromTengwarToEnglish(std::string str)
{
    return "Hello world.";
}

The problem is, I keep getting 'multiple definition of numbers[abi:cxx11]' errors, when invoke translateFromTengwarToEnglish in my main function, even though I'm fairly certain I have only defined it once, in my header file, using header guards too. In case it might help, here is my humble main cpp file:

#include "mainwindow.h"
#include <QApplication>

#include <iostream>

#include "utils/tengwarlibrary.h"

int main(int argc, char *argv[])
{

    std::string s = "BlaH FElfeFEJI, IEORlfj";
    std::cout<<translateFromEnglishToTengwar(s)<<std::endl;

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
4
  • You can only declare symbols with external linkage in a header file. Their definition needs to be in the translation units using them. Commented Apr 9, 2017 at 7:53
  • @HenriMenke I have gotten the same error when I remove the extern const bit and just assume it's a global variable. I don't really want to have to put a definition into the source file when I can use an initializer in the header. Commented Apr 9, 2017 at 7:55
  • @AndrewLalis You cannot. The way you wrote it, each source file implicitly gets a definition of the numbers array. You should declare the array in the header and define it (without the extern keyword) in exactly one source file. Commented Apr 9, 2017 at 7:57
  • @HellmarBecker so should I just make an 'init' function in one of my sources that defines all the arrays I'll need? Commented Apr 9, 2017 at 8:03

2 Answers 2

7

According to C++ standard §3.1.2

A declaration is a definition unless it declares a function without specifying the function’s body, it contains the extern specifier or a linkage-specification and neither an initializer nor a function-body ...

Declaration of numbers in the header file tengwarlibrary.h is extern declaration with initializer. So it is also a definition.

As you have included tengwarlibrary.h in two source files (one where translateFromTengwarToEnglish() is defined and where main() defined) both of them has the definition of numbers. Hence, the error.

To solve this problem declare number with extern in header file and initialize it in a single source file.

Sign up to request clarification or add additional context in comments.

Comments

1

This seems to be an issue with the most recent versions of GCC. In my case, this error appeared while running a C project on a docker container (Alpine image). However, it did not appear when I ran the same project using an older GCC version (9.4.0).

What fixed it for me was adding the extern keyword to the global variables/functions that presented the issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.