0

I have following template class constructor for an exception class:

MyCustomException.h:

template<typename ... Args>
MyCustomException(const Message& msg, const char* fileName, int line, Args&& ... args);

MyCustomException.cpp:

template<typename ... Args>
MyCustomException(const Message& msg, const char* fileName, int line, Args&& ... args) {
  // random magic here
}

Now, when I am trying to pass it a const char* (e.g. in main.cpp):

#include "MyCustomException.h"

// ...

void myFunc() {

  try {
    // ...
    const Message m { id, msg };
    const char* mychar { "test string" };
  
    if (someCondition) {
      throw MyCustomException(m, __FILE__, __LINE__, mychar);
    }
  catch (MyCustomException& e) {
    // ...
  }
}

// ...

int main() {
  myFunc();
}

I keep getting a linker error LNK2019 (unresolved external symbol):

public: __cdecl MyCustomException::MyCustomException<char const *>(class Message const &,char const *,int,char const *)

When passing it a string literal, everything works just fine.

What's the deal with variadic template parameters and const char*?

tai
  • 477
  • 1
  • 5
  • 16
  • First of all, identifiers starting with a double underscore are reserved for the implementation, don't use them. – Fareanor Nov 12 '21 at 13:29
  • @Fareanor what do you mean? I do use them in the implementation (when throwing the exception), they're not custom-defined. – tai Nov 12 '21 at 13:30
  • 1
    @Fareanor the values of `__FILE__` and `__LINE__` are filled in by the compiler's implementation. – Sergey Kalinichenko Nov 12 '21 at 13:33
  • 2
    Just a guess but... are you trying to implement your [template members in a separate `.cpp` file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file)? – G.M. Nov 12 '21 at 13:34
  • @G.M. well yes I am! But how can this linker error be different when passing different types? – tai Nov 12 '21 at 13:37
  • @G.M. alright, got it, thanks for your hint, that solves it. – tai Nov 12 '21 at 13:44
  • `"test string"` is not a `const char*`, but a `const char [12]`. you probably instantiated the later, which hides the issue from your testing. – Jarod42 Nov 12 '21 at 13:47
  • @SergeyKalinichenko Oh my bad, I didn't know these macros, thanks for the correction. – Fareanor Nov 12 '21 at 14:00

1 Answers1

0

The problem was with defining the template constructor inside a separate .cpp file. As G.M. linked to this post in the comments, template members should be implemented in the header file or, when defined in the .cpp file, at least be defined explicitly for each instance.

tai
  • 477
  • 1
  • 5
  • 16
  • 1
    answering your own question is fine, but note that in the current state the question is missing crucial information (only you can know what the issue was) and once the question is fixed it should be closed as duplicate of https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – 463035818_is_not_an_ai Nov 12 '21 at 13:55