19

Could anyone help me with the following problem?

There is a simple code:

#include <vector>

struct A {
    std::vector<int> vec;
};

void func (A &&a = {}) {}

int main()
{
    func();
    return 0;
}

When I try to compile it by gcc 5.4.0 I get the error:

undefined reference to `std::vector<int, std::allocator<int> >::vector()'

Amazingly, but clang compiles it well. Also if to modify the code a little bit it is compiled without any problems:

#include <vector>

struct A {
    std::vector<int> vec;
};

void func (A &&a) {}

int main()
{
    func({});
    return 0;
}

I really cann't understand what's wrong with the first code.

  • Could you provide command line you use for compiling? Are you using g++? – Marek Vitek Jun 16 '17 at 11:53
  • I tried gcc 6.3.0 with the same result. Only clang works well as I mentioned. – Алексей Шалашов Jun 16 '17 at 11:53
  • @NathanOliver , it seems that my description was a bit misleading. Object file will be compiled well but when you start linkage to get binary you'll get the same issue. You can see it also with online compiler you reffered. Just push "Compile to binary". – Алексей Шалашов Jun 16 '17 at 12:10
  • Are you using by any chance some self-installed gcc on Mac OSX? I could reproduce your error on my mac book with a homebrew installation of gcc 6.2.0 that was somehow compromised (and also produced several warnings in the compilation process itself). – Walter Jun 16 '17 at 12:14
  • Oh, wow. Tried [here](http://coliru.stacked-crooked.com/a/9d1ea8b67f83aff3) and got the same results. – NathanOliver Jun 16 '17 at 12:15
  • @MarekVitek , the command is simple: $ g++ -std=c++11 -o main.x main.cpp /tmp/ccoaMpv0.o: In function `main': main.cpp:(.text+0x1b): undefined reference to `std::vector >::vector()' collect2: error: ld returned 1 exit status – Алексей Шалашов Jun 16 '17 at 12:15
  • Reproduced on Wandbox: https://wandbox.org/permlink/iLVJFtVkCWebXntD. – ks1322 Jun 16 '17 at 12:16
  • Looks like you've uncovered a bug of gcc. You should report it. The strange thing is that the missing symbol is generated from a `template` and hence fully `inline`. The compiler should have generated that, rather than asking the linker to load it. – Walter Jun 16 '17 at 12:17
  • 4
    Might be the same cause as [this bug report](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68070) – NathanOliver Jun 16 '17 at 12:22
  • I was looking in wrong direction. This might be some issue with gcc. I have maybe interesting note, I tried to add following line ` A && x = {};` between call to func and return. Suddenly it compiles without eror. – Marek Vitek Jun 16 '17 at 12:22
  • 1
    Same problem if you replace `vector` with `list` (or any other templated container I suppose). – Walter Jun 16 '17 at 12:24
  • 1
    @NathanOliver That is indeed the answer. Please write it up. – Walter Jun 16 '17 at 12:26
  • 1
    It's acctualy not a vector problem: https://wandbox.org/permlink/7ZZrMnzOUX6hdOxb – xinaiz Jun 16 '17 at 12:27
  • @Black Moses yes it is not problem with vector. It is problem with instantiation of template in this specific scenario. See my Answer with code example. – Marek Vitek Jun 16 '17 at 13:13

2 Answers2

11

This is a gcc bug. It can also be reproduced with

template<typename Value>
struct A
{
    A() = default;
    std::vector<Value> m_content;
};

void func(A<int> a = {})
{
}

int main()
{
    func();
}

Currently though, there is no status on it.

I appears that the lack of an actual instance of the vector is causing the compiler to not stamp out the code for it which leads to the undefined reference.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
3

As @NathanOliver mentioned, this is a GCC bug. What is the bug? It seems to me that it forgets to instantiate a class std::vector<int> when it is used as a function parameter and enclosed in another type.
You can work around it by using A somewhere else in the code. Even a simple declaration is enough. It forces the compiler to instantiate the templated type and you are good. Look for A unused in the code below that will compile.

#include <vector>

struct A {
    std::vector<int> vec;
};

void func (A &&a = {}) {
    A unused;
}

int main()
{
    func();
    return 0;
}
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
Marek Vitek
  • 1,573
  • 9
  • 20