0

As far as I know, ld: symbol(s) not found for architecture happens when you don't provide an implementation for a function that is declared and used.

I'm getting that error, but I AM providing the implementation. As a proof, I intentionally added an (not-working) implementation in the header file and then I get error: redefinition of... error.

Here is the excerpt from each file:

MyBlob.hpp

template <typename Element>
class MyBlob
{
public:
  Element &operator[](std::size_t);
  const Element &operator[](std::size_t) const;
};

MyBlob.cpp

#include "MyBlob.hpp"

using namespace std;

template <typename Element>
Element &MyBlob<Element>::operator[](size_t i)
{
  return *this[i];
}

template <typename Element>
const Element &MyBlob<Element>::operator[](size_t i) const
{
  check(i, "subscript index out of range");
  return *data[i];
}

MyBlob_test.cpp

#include "MyBlob.hpp"
// and other includes

using namespace std;

int main()
{
  MyBlob<string> sblob{"foo", "bar"};
  cout << sblob[0] << endl;
}

All three files are in the same folder, and here is the command: $ g++-12 MyBlob_test.cpp MyBlob.cpp MyBlobPtr.cpp

The error message:

Undefined symbols for architecture x86_64:
  "__ZN6MyBlobINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEixEm", referenced from:
      _main in ccSGsKtO.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

And here is what happens when I intentionally provide an inline implementation like so:

MyBlob.hpp

Element &operator[](std::size_t) { } // not a correct implementation but doesn't matter
In file included from MyBlob_test.cpp:1:
MyBlob.hpp: In instantiation of 'Element& MyBlob<E>::operator[](std::size_t) [with Element = std::__cxx11::basic_string<char>; std::size_t = long unsigned int]':
MyBlob_test.cpp:23:10:   required from here
MyBlob.hpp:44:38: warning: no return statement in function returning non-void [-Wreturn-type]
   44 |   Element &operator[](std::size_t) { }
      |                                      ^
MyBlob.cpp:14:10: error: redefinition of 'Element& MyBlob<E>::operator[](size_t)'
   14 | Element &MyBlob<Element>::operator[](size_t i)
      |          ^~~~~~~~~~~~~~~
In file included from MyBlob.cpp:1:
MyBlob.hpp:44:12: note: 'Element& MyBlob<E>::operator[](std::size_t)' previously declared here
   44 |   Element &operator[](std::size_t) { }
      |            ^~~~~~~~

What is going on here?

I feel like the two are mutually exclusive: either I'm not providing an implementation and the linker failed to find and implementation so inlining the implementation should work, or I am providing an implementation so it should compile normally and fail only when I redefine the function.

funct7
  • 3,407
  • 2
  • 27
  • 33
  • 1
    To instantiate a template function/class, compiler must see the definition of that in the translation unit where the instantiation is seen. In your second example, there is still no instantiation (and it would likely fail on linking `main.cpp` as well), but that doesn't matter - you have two different definitions and linker can reject that program when it builds a reference table, not later on lookup. – Yksisarvinen Oct 12 '22 at 11:41

0 Answers0