mistificator
капелюх чарiвника
Давно имелись подозрения, что не всё гладко в реализации шаблонов в компиляторе Borland'a (bcc32, Borland C++ Compiler). Borland благополучно отошёл от разработки компиляторов, предоставив свои детища CodeGear'у. Те немного подретушировали компилятор, подправив в нём откровенные несоответствия современным стандартам С++ (добавив, в частности, поддержку неименованных union как в MSVC++), но некоторые проблемы с реализацией шаблонов всё же остались.
Одна из них заключается в том, что приведенный ниже код не компилируется компилятором bcc32.

//------------------------------------------------------------
template <class T, int Value>
class A {
public:
union {
T a[Value];
char b[Value * sizeof(T)];
}
};


int main() {
A<int, 1> Obj;
Obj.b[0] = 1;
Obj.b[1] = 0;
Obj.b[2] = 0;
Obj.b[3] = 0;
cout << Obj.a[0] << endl;
return 0;
}
//------------------------------------------------------------

Компилятор заявляет, что невозможно вычислить sizeof(T) (хотя тип T известен на стадии компиляции), и что Value является неопределенным идентификатором. На самом деле, компилятор заблуждается, а проблема заключается в том, что он не может вычислить математическое выражение, подставленное в качестве размера массива. Оказывается, если вычислить выражение, объявив enum, то всё будет нормально. Так же, через объявление enum, решается проблема с "неопределенностью" Value.
Перепишем код.

//------------------------------------------------------------
template <class T, int Value>
class A {
public:
enum {__Value = Value };
enum {__Size = Value * sizeof(T)};
union {
T a[__Value];
char b[__Size];
}
};


int main() {
A<int, 1> Obj;
Obj.b[0] = 1;
Obj.b[1] = 0;
Obj.b[2] = 0;
Obj.b[3] = 0;
cout << Obj.a[0] << endl;
return 0;
}
//------------------------------------------------------------

Теперь код компилируется и выполняется.
Приведенная выше проблема является одним из камней преткновения, вследствие которых Qt 4 не компилируется компиляторами bcc32.

@темы: Нетривиальный вызов, Трюки с шаблонами