2 Answers

In C++, you usually have to define template functions inside the header file. Here is a better explanation.

Also, you might need to add GAZEBO_VISIBLE macro to your functions if you want them to be available elsewhere. This won't apply to your template classes/function though. You'll need to include gazebo/util/system.hh to get the macro.

What fixed it, was changing the join function from a template function, to an overloaded function. I assume this fixed it because I was misusing template functions somehow.

Side information:

It was failing at runtime, because it's a shared library. Shared libraries have some of the linking process done at runtime, unlike static libraries. Presumably, this means the compiler gives it some leniency at compile time, meaning it does not fail. I did not realize this, and was thoroughly confused by the idea of a c++ program failing like that at runtime. More info here.

The reason the symbol came out all wierd looking,(_Z4joinIdENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS0_4listIT_SaIS7_EEES5_) was because c++ was doing something called "mangling", which occurs when a function appears more than once in a single namespace. For example, when overloading a function. The symbol came out as expected when using the "nm" command with the "-C" flag, or piping it into the "c++filt" command. Learn more about mangling here.

Ultimately, the problem and solution revealed itself when I took a step back and took the time to learn the tools I'm using, not just randomly changing things, hoping it would fix itself. Problems that seemed bewildering and nonsensical made a great deal more sense once I took the time to carefully read the docs and man pages. Who knew?