Please check the following small program:
#include <stdio.h>
template<typename USER_TYPE, typename RET_TYPE, RET_TYPE (*pfn)(USER_TYPE), USER_TYPE valInvalid>
class CEnsureCleanup_array
{
int m_ArraySize;
USER_TYPE *m_ar; // This member representing the object array ptr
public:
// Default constructor clears all pointer elements to invalid-value
CEnsureCleanup_array(int ArraySize) : m_ArraySize(ArraySize) {
m_ar = new USER_TYPE[m_ArraySize];
for(int i=0; i<m_ArraySize; i++) m_ar[i] = valInvalid;
}
// The destructor performs the cleanup.
~CEnsureCleanup_array() { Cleanup(); }
// Helper methods to tell if the value represents a valid object or not..
int IsValid(int idx) { return(m_ar[idx] != NULL); }
int IsInvalid(int idx) { return(!IsValid(idx)); }
USER_TYPE& operator[](int idx) {
return m_ar[idx];
}
operator USER_TYPE*() {
return m_ar; // Return the address of the first array element.
}
void Cleanup()
{
for(int i=0; i<m_ArraySize; i++)
if (IsValid(i)) {
pfn(m_ar[i]); // Cleanup the object.
}
delete m_ar;
}
};
struct MyClass
{
int m_i;
MyClass(int i) : m_i(i) {}
~MyClass() {
printf("MyClass dtor(%d)\n", m_i);
}
};
#define MakeCleanupClass_array(CecClassName, RET_TYPE_of_CleanupFunction, pCleanupFunction, USER_TYPE, valInvalid) \
typedef CEnsureCleanup_array<USER_TYPE, RET_TYPE_of_CleanupFunction, pCleanupFunction, valInvalid> CecClassName;
void DeleteMyClass(MyClass *p){ delete p; }
MakeCleanupClass_array(CecMyClass, void, DeleteMyClass, MyClass*, 0)
int main()
{
CecMyClass armc(2);
// By using CecMyClass, armc[0] & armc[1] can be automatically deleted
// on `armc' destruction.
armc[0] = new MyClass(0);
armc[1] = new MyClass(1);
return 0;
}
It compiles OK on Microsoft Visual Studio.NET 2005 or even MSVC
6.0 SP6ïand the output is:
MyClass dtor(0)
MyClass dtor(1)
However, with gcc 4.1.0(SUSE Linux), compilation error:
t1.cpp:56: error: could not convert template argument '0' to 'MyClass*'
t1.cpp:56: error: invalid type in declaration before ';' token
t1.cpp: In function 'int main()':
t1.cpp:63: error: invalid types 'CecMyClass[int]' for array subscript
t1.cpp:64: error: invalid types 'CecMyClass[int]' for array subscript
I'm really baffled! Since 0 can be assigned to any pointer
variable, then why "0 could not be converted to MyClass* "?
Furthermore, if a try to change the line just above the main()
definition to:
MakeCleanupClass_array(CecMyClass, void, DeleteMyClass, MyClass*, (MyClass*)0)
Compiler error changes to:
t1.cpp:56: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
t1.cpp:56: error: template argument 4 is invalid
t1.cpp:56: error: invalid type in declaration before ';' token
t1.cpp: In function 'int main()':
t1.cpp:63: error: invalid types 'CecMyClass[int]' for array subscript
t1.cpp:64: error: invalid types 'CecMyClass[int]' for array subscript
I really cannot figure out why gcc spout those errors while that
case of template usage has very clear meaning and is absolutely
unambiguous.
Can you dear gcc developers give me an explanation?