• he/him

programming, video games, dadding. I happen to work for Xbox, but don't represent them.


more blog
dev.to/knutaf
discord
knutaf

PolyWolf
@PolyWolf

Why doesn't the following code run? (comments represent different files):

// foo.hpp
template <typename T>
struct Foo {
  static void foo(void);
}
// foo.cpp
#include <iostream>
#include "foo.hpp"
template <>
struct Foo<int> {
  static void foo() { std::cout << "foo\n"; }
}
// main.cpp
#include "foo.hpp"
int main(void) {
  Foo<int>::foo();
}
syntax highlighting by codehost

Answer

From this SO post. Basically, foo.cpp needs to be

#include <iostream>
#include "foo.hpp"
template struct Foo<int>;
void Foo<int>::foo() { std::cout << "foo\n"; }
syntax highlighting by codehost

because otherwise, member function definitions are secretly inline, and since there is no usage site in the same compilation unit they won't get exported as symbols. Declaring them like this lets them be non-inline, and the symbol can be used in the other compilation unit.

hell language btw.


You must log in to comment.

in reply to @PolyWolf's post:

I am doing this for a "serialization" library where the possible serializations are not known beforehand, and I would rather not have to worry about including all the correct headers for overloaded functions for each serializable type. But perhaps messing that up is a better message than linker errors where u have no idea what compilation unit caused it. I'll need extra headers anyways for the partial specialization stuff i plan on doing.

C++ was a mistake haha