When compiling (Microsoft Visual C++ 2005 Express) this piece of code:
struct A
{
template< typename T > static A Foo( void ) { return A(); }
struct S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
A ( *m_funcFoo )( void );
};
};
int main(int argc, char* argv[])
{
A::S::GetInstance< int >();
}
I get a C2440 error:
'=': cannot convert from 'A (__cdecl *)(void)' to 'A (__cdecl *)(void)'
That doesn't make sense to me. The two types named in the error text are obviously the same.
Also, when changing Foo
's return value to int
, there is no such error.
Is it a bug or am I doing something wrong?
EDIT : So, if it's a bug, does anyone know how to solve this? Maybe by using casts? I need this code to compile...
It's a compiler bug. VC++ is doing something very weird.
For example, this generates a very different error message:
struct A
{
template< typename T > static struct A Foo( void ) { return A(); }
struct S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
A ( *m_funcFoo )( void );
};
};
sourceFile.cpp(5) : error C3856: 'A::Foo': class is not a class template
And this works:
struct X {};
struct A
{
template< typename T > static X Foo( void ) { return X(); }
struct S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
X ( *m_funcFoo )( void );
};
};
Clearly it's getting confused by the name A
, which should refer to the base class.
Adding a typedef didn't help, neither does a forward declaration of struct A
, neither does qualifying the name as ::A
or struct A
.
Oddly enough, VC++7 compiles it fine.
Workaround: Changing it like this:
struct A
{
template< typename T > static A Foo( void ) { return A(); }
struct S;
};
struct A::S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
A ( *m_funcFoo )( void );
};
inverts the result, now VC++8 compiles ok and VC++7 generates the same error message.
I think there's a type identity issue between an incomplete type and the same type after completion.
All tests run using the Dinkumware Multi-Compiler Test Tool
I am not sure if it is a compiler bug or not, but at least it is documented on msdn.
I don't have a 2005 compiler at hand but vs2010 compiles your code if write it like this:
struct A
{
template< typename T > static A Foo( void ) { return A(); }
struct S
{
A ( *m_funcFoo )( void );
template< typename T > static S GetInstance( void );
};
};
template< typename T >
A::S A::S::GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
Looks like a bug -- it compiles fine on Comeau (http://www.comeaucomputing.com/tryitout).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With