#include <iostream>
template <typename T>
class Foo
{
public:
enum {
x
};
};
template <typename T>
class Bar
{
public:
int y;
Bar()
:y(10)
{}
void poof()
{
Foo<T>::x*y; // declaration or multiplication?
std::cout << "poof" << y << std::endl;
// the executabel compiled by g++ will print the poof10
// so g++ think Foo<T>::x*y is multiplication
// the executable compiled by CC will print the poof0
// so CC think Foo<T>::x*y; is declaration of a pointer
// after you add the typename prefix before Foo<T>::x*y;
// then both g++ and CC know it is a associated type
}
};
// evil specialization
template <>
class Foo<void>
{
public:
typedef int x;
};
int main()
{
Bar<void> bomb ;
bomb.poof();
}
The compiler will be confused with
Foo<T>::x*y;It may be multiplication if T is not void, or a pointer declaration if T is void. g++ and CC has different default assumptions, g++ think it is multiplication, but CC thinks it is declaration of a pointer.
When do we need add the typename prefix?
- from ``C++ template the complete guide'' Chp 9.3.2,