0

When I specialize an int-templated function with a negative value defined in hexadecimal, Visual Studio 2010 give me a strange "1 unresolve externals" link error.

Still it works fine if:

  1. I define the negative int value in decimal form.
  2. I define the template argument with "unsigned int" instead of "int".
  3. I use directly "DefaultMsg" templated-function. I.e. it only fails when I use "NewMsg" templated-function which calls "DefaultMsg" templated-function.

Then I have some workaround here, but I still do not understand what is going wrong. Am I doing something bad ? Or is it a tricky compiler bug/limitation case ?

Here is a sample code:

// Compile condition: define a code in hexa or decimal
#define DEFINEHEXANOTWORKING    1

// Code
#define CODE1   1
#define CODE2   0x2
#if !DEFINEHEXANOTWORKING
    // Here define a negative code in decimal mode
    #define CODE3   -1
#else
    // Here define a negative code in hexadecimal mode
    #define CODE3   0xFFFFFFFF
#endif

// Default message declaration
template<int r> __forceinline const char* DefaultMsg();

// Default message specialization
template<> __forceinline const char* DefaultMsg<CODE1>()    { return "Message 1."; }
template<> __forceinline const char* DefaultMsg<CODE2>()    { return "Message 0x2."; }
template<> __forceinline const char* DefaultMsg<CODE3>()    { return "Message -1/0xFFFFFFFF."; }

// New template message
template<int r> __forceinline const char* NewMsg()          { return DefaultMsg<r>(); }

// Main test
int _tmain(int argc, _TCHAR* argv[])
{
    // Print default messages, all working in all cases
    printf("Default messages:\n");
    printf("CODE1: %s\n", DefaultMsg<CODE1>());
    printf("CODE2: %s\n", DefaultMsg<CODE2>());
    printf("CODE3: %s\n", DefaultMsg<CODE3>());

    // Print new messages, not working if defined in hexa mode
    printf("\nNew messages:\n");
    printf("CODE1: %s\n", NewMsg<CODE1>());
    printf("CODE2: %s\n", NewMsg<CODE2>());
    printf("CODE3: %s\n", NewMsg<CODE3>()); // Not compiling line in hexa mode

    _getch();
    return 0;
}

The compiler error:

error LNK2019: unresolved external symbol "char const * __cdecl DefaultMsg<-1>(void)" (??$DefaultMsg@$0?0@@YAPBDXZ) referenced in function "char const * __cdecl NewMsg<4294967295>(void)" (??$NewMsg@$0PPPPPPPP@@@YAPBDXZ)
1>D:\§CELII\Tests de programmation\2017-08-16 - Test template\Debug\2017-08-16 - Test template.exe : fatal error LNK1120: 1 unresolved externals 
Cœur
  • 37,241
  • 25
  • 195
  • 267
Charly
  • 11
  • 2
  • This is the error you get with `#define DEFINEHEXANOTWORKING 1` or without it ? – 463035818_is_not_an_ai Aug 16 '17 at 11:59
  • I don't understand what you are doing/trying to do here! Templates are used for different types not for passing parameters – o_weisman Aug 16 '17 at 12:06
  • @tobi303 Yes I get the error with the `#define DEFINEHEXANOTWORKING 1`. With `#define DEFINEHEXANOTWORKING 0`, i.e. when defining constant using decimal, it compiles fine. – Charly Aug 16 '17 at 12:26
  • @o_weisman See [link](https://stackoverflow.com/questions/499106/what-does-template-unsigned-int-n-mean) – Charly Aug 16 '17 at 12:30
  • Hex constants are treated as unsigned. https://stackoverflow.com/questions/4737798/unsigned-hexadecimal-constant-in-c – Albjenow Aug 16 '17 at 12:31
  • I second @o_weisman, what you have there looks a bit overengineered as you already have macros you could simply do `printf("CODE1: %s\n", CODE1);` and define `CODE1` as the message itself, instead of a parameter that you pass to a template to get the message – 463035818_is_not_an_ai Aug 16 '17 at 12:31
  • @tobi303 Thank you for the _overengineered_, it is a sample case. In the real code I need both int-bitfields codes values and messages. @Albjenow If so, why compiler is searching for `DefaultMsg<-1>(void)` ? – Charly Aug 16 '17 at 12:42
  • @Charly I was suspecting something like that and the "overengineered" was of course only with respect to not knowing what you actually want to achieve. However, if you need both bitfields values and messages, I would probably just use a `std::string bitF2message(bitfield);` ... not sure if it is worth the effort trying to push everything to compile time – 463035818_is_not_an_ai Aug 16 '17 at 12:52
  • Must admit I was unaware of this use for templates – o_weisman Aug 16 '17 at 13:19

0 Answers0