views:

51

answers:

1

So say I have the following very simple macro, along with a bit of code to output it:

#define SIMPLEHASH(STRING) STRING[1] + STRING[2] + STRING[3]

std::cout << SIMPLEHASH("Blah");

This outputs 309, and if you view the assembly you can see:

00131094  mov         ecx,dword ptr [__imp_std::cout (132050h)] 
0013109A  push        135h 
0013109F  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13203Ch)] 

Where 135h translates nicely into 309 decimal. Everything was compiled away to a constant.


Now, say you have a template class as such:

template<int X> class Printer{
public:
 void Print(){
  std::cout << X;
 }
};

Then the following will nicely print the number 32:

Printer<32> p; p.Print();


Both these things work individually, the problem comes when you try to combine them:

#define SIMPLEHASH(STRING) STRING[1] + STRING[2] + STRING[3]
 Printer<SIMPLEHASH("Blah")> p;
 p.Print();

In visual studio this gives:

1>.\ShiftCompare.cpp(187) : error C2975: 'X' : invalid template argument for 'Printer', expected compile-time constant expression
1>        .\ShiftCompare.cpp(127) : see declaration of 'X'

Despite the fact that SIMPLEHASH("Blah") can be reduced to a constant at compile time, as seen in the first example.

So, what gives, is there a way to tell the compiler "evaluate this first"? are templates naturally "before" macros in preprocessor evaluation?

Does anyone see any way I can get these two to work together?

+5  A: 

Macros are evaluated before the source is fully parsed and preprocessing has nothing at all to do with templates.

The problem is that the template argument with which you instantiate Printer must be a constant expression and you cannot use a string literal in a constant expression.

James McNellis