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.