I have a Visual Studio 2012 project equivalent to this:
Header.h
template< class T >
inline int Demonstrate( const char *txt, T *input )
{
return printf("%s %d %f\n", txt, input->Integer(), input->Real() );
}
Source.cpp
#include "Header.h"
class Foo
{
public:
int Integer() { return 2; }
float Real() { return 3.14159f; }
};
int main()
{
Foo example;
printf( "%d\n", Demonstrate( "foo:", &example ) );
return 0;
}
Yet when I compile I receive a LNK2019 error:
unresolved external symbol "int __cdecl Demonstrate(char const *,class Foo *)"
Ordinarily this occurs when a templated function is declared in a header but only defined in a cpp, but that is not the case here. The function is defined inline in the header.
What could cause this and how can I fix it?
edit
This happens even if I remove the header altogether and just stick Demonstrate() at the top of Source.cpp. It happens whether "Inline Function Expansion" in the project properties is set to "Default" or to "/Ob2" . This must be some project settings thing, but what?
So I tracked this down and it turns out that Joel was on the right path. The function Demonstrate() had been prototyped multiple times in multiple headers — in a very nonobvious way. There was the explicit int Demonstrate( const char *txt, Foo *input ) declaration, which is what I replaced with a template.
But there were several other headers that had, strewn across them, something analogous to this (you can infer that the actual function and class names were much more complicated):
header a.h:
#define FUNC_PREFIX Demo
header b.h:
#define REGISTER_CLASS( retype, classname, FUNC_SUFFIX ) retype FUNC_PREFIX ## FUNC_SUFFIX ( const char *txt, classname *ptr )
header c.h:
REGISTER_CLASS( int, Foo, nstrate );
REGISTER_CLASS( int, Bar, nstrate );
// etc
I'm not sure what to draw from this. On the one hand it's a very specific bug to a very specific codebase and too localized to be a useful SO question. On the other hand, there is a teachable moment here:
DON'T USE MACROS TO DEFINE GLOBAL FUNCTIONS IN SNEAKY WAYS.
Or else poor saps like me will spend hours tracking down problems like this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With