3

I have a class with a template method that is declared in a header and defined in a cpp file, so

// A.h - declaration
struct A
{
    template<typename T = int> void fun();
};

and then

// A.cpp - definition
#include <iostream>
#include "A.h"

template<typename T> void A::fun()
{
    std::cout << "Hello world template" << std::endl;
}

// Explicit instantiation
template void A::fun<int>();

Now, somewhere else, in a test, I have

#include "A.h"

int main ()
{
    A a;
    a.fun();
}

and since I explicitly instantiated the function for int template parameter, all is well. Or should be!

My code links fine with GCC 7.3.0 but fails to link with clang 6, which reports an undefined reference to function fun.

What's going on here? Is there anything else that I should take care of? Perhaps something that GCC takes for granted while clang doesn't?

Thanks!

Edit

@WhozCraig, @Neil Butterworth here are the linking commands for the two toolchains.

GCC:

/usr/bin/g++  -g   CMakeFiles/test_generator.dir/generator/generator.cpp.o CMakeFiles/test_generator.dir/test_utils.cpp.o  -o test_generator -Wl,-rpath,/home/mleoni/PhD/ABI/libcellml/build/src:/home/mleoni/PhD/ABI/libcellml/build/tests/gtest ../src/libcellmld.so.0.1.0 gtest/libgtest_main.so /usr/lib/x86_64-linux-gnu/libxml2.so gtest/libgtest.so -lpthread

clang:

/usr/bin/clang++  -g   CMakeFiles/test_generator.dir/generator/generator.cpp.o CMakeFiles/test_generator.dir/test_utils.cpp.o  -o test_generator -Wl,-rpath,/home/mleoni/PhD/ABI/libcellml/build/src:/home/mleoni/PhD/ABI/libcellml/build/tests/gtest ../src/libcellmld.so.0.1.0 gtest/libgtest_main.so /usr/lib/x86_64-linux-gnu/libxml2.so gtest/libgtest.so -lpthread

@IdeaHat: that didn't resolve the issue unfortunately, I am still getting the same error

Edit 2 Since the code I am actually trying to compile is [obviously] not that one, I tried to compile this MWE and both GCC and clang link it fine with just cc A.cpp main.cpp.

I am now trying to understand what's the difference between this minimal case and the code that I actually have.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
  • 1
    Before anyone else makes that jump, the OP is purposely explicitly instantiating `A::fun()` in A.cpp. Along with the default template argument for `A::fun`, the question is why does one toolchain seem to do the expected (link) and another wouldn't. I'd like to see the build commands for both to ensure something mundane like failing to compile/link A.cpp for one vs. the other isn't the difference. Please update your post to include both build commands. – WhozCraig Oct 18 '18 at 23:05
  • 1
    OK - how is this code being linked? –  Oct 18 '18 at 23:07
  • possible duplicate of https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix – eerorika Oct 18 '18 at 23:12
  • 1
    Can you try adding `extern template void A::fun();` to the header? – IdeaHat Oct 18 '18 at 23:54
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) –  Oct 19 '18 at 02:02

1 Answers1

0

I found it. Somewhere in this code base I am not familiar with all classes are marked private by default [as in Windows D:] and after I marked my class public clang could finally link correctly.

Now the plot thickens because with the binaries compiled by clang I see a lot of segfaults in the test suite that are not present when compiled with GCC.

Also, now I have the same question as the one in this thread, except now GCC and clang work fine while MSVC says unresolved external symbol :'( .