7

I have a mini project with two files:

main.cpp

#include <string>
template<int I>
int getint(int i)
{
    extern std::string var;
    return var.size() * i;
}

int main()
{
    return getint<2>(2);
}

and sub.cpp

#include <string>
extern std::string var;
std::string var = "Hello";

But when I compile the project, the linker gives the error:

-------------- Clean: Debug in test (compiler: GNU GCC Compiler)---------------

Cleaned "test - Debug"

-------------- Build: Debug in test (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe -Wall -fexceptions -g  -c C:\Users\Fan\Downloads\test\test\main.cpp -o obj\Debug\main.o
mingw32-g++.exe -Wall -fexceptions -g  -c C:\Users\Fan\Downloads\test\test\sub.cpp -o obj\Debug\sub.o
mingw32-g++.exe  -o bin\Debug\test.exe obj\Debug\main.o obj\Debug\sub.o   
obj\Debug\main.o: In function `Z6getintILi2EEii':
C:/Users/Fan/Downloads/test/test/main.cpp:6: undefined reference to `var'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
2 error(s), 0 warning(s) (0 minute(s), 0 second(s))

I have no clue how this happens, because as long as I simplified the program a little, the problem goes away.

  1. If I make getint() a plain old function instead of a function template, then the compilation succeeds.

  2. If I move the line "extern std::string var;" outside the function (say to one line above it), then the compilation succeeds.

  3. If I change the type of var to an int (and omit ".size()" in main.cpp, and assign 1 to it in sub.cpp), then the compilation succeeds.

It seems a weird combination of factors that prevent my original project from compiling. I have no idea what they are :(

Edit: In response to the "cannot reproduce" remark, I am trying the compilation on my local windows 7 machine using Code::Blocks 17.12. Output of the compiler and the linker has been updated to include compiler flags.

Fan Zheng
  • 171
  • 3
  • Cannot reproduce: http://coliru.stacked-crooked.com/a/aebbaf78ae41fc64 ... What compiler version and flags do you use? – user1810087 May 25 '20 at 09:54
  • Also can't reproduce [here](https://onlinegdb.com/HkUSIfYsI), and neither on my local machine (with MSYS2 GCC, nor with Clang). What compiler (including version) do you use? – HolyBlackCat May 25 '20 at 09:56
  • nice trick with the #ifdef MAIN :) – yaodav May 25 '20 at 09:59
  • Addendum to cannot reproduce; Nor with Visual Studio 2019 and 2017. – user1810087 May 25 '20 at 10:14
  • 2
    *"using Code::Blocks 17.12"* CB is known to ship with an ancient compiler. This may or may not be a compiler bug, but in any case, you should update the compiler. – HolyBlackCat May 25 '20 at 10:57
  • I can compile this. However, i suspect the 'extern std::string var` appearing two times may result in that error message in some other compiler or other compiler version. The `sub.cpp` defines the `std::string var`. It should not contain an extern keyword. – Wör Du Schnaffzig May 25 '20 at 11:51
  • 1
    Quick confirmation: Code::Blocks 17.12 uses [GCC 5.1.0](https://sourceforge.net/projects/codeblocks/files/Binaries/17.12/Windows/), and GCC 5 (gcc version 5.5.0 20171010 in this test case) [does not compile this](http://coliru.stacked-crooked.com/a/0b73d411b3981bb5). – user1810087 May 25 '20 at 13:09
  • @pqans extern std::string var removed and still doesn't compile in the link given by user1810087 – Fan Zheng May 26 '20 at 00:08
  • Try gcc with -S option for the main and the sub so that you may see if there is some decoration issue – Wör Du Schnaffzig May 26 '20 at 10:44
  • @pqans I saw var has the name __Z3var in main.o but __Z3varB5cxx11 in sub.o – Fan Zheng May 27 '20 at 07:52
  • This is obviously a decoration issue. The question is, what's the reason for the different decoration in main and sub? – Wör Du Schnaffzig May 27 '20 at 09:15

0 Answers0