Template specialisation fail VC2005 - Types not resolved
- Hi all, I have a problem compiling some templated C++ code in Visual Studio 2005. The compiler seems unable to resolve the types used in a function pointer template parameter for a method within a specialised template class (bit of a mouthfull... the code may have to speak for itself).
The example code below contains two sample classes. ClassA contains undesirable template syntax but demonstrates that function pointers can be used as template parameters using templated types. ClassB is defined using the desired syntax (using template specialisation), however raises error C2440 when a function pointer is passed to the TestMe method.
It seems this error is due to the specialisation of ClassB. I used template specialisation specifically so that the template parameter to the class could be a single function pointer type. As you can see from the error (commented in the TestCase function), the types should match up!
I should mention, I am using Visual Studio 2005 to compile the code in this thread. This code compiles fine in Visual Studio 2008 and in gcc on Windows and Linux. This post is just about the broken Visual Studio 2005 compile.
template < typename ReturnType, typename ParamType > class ClassA { public: template < ReturnType (*Func)(ParamType) > void TestMe() { } }; template < typename T > class ClassB; template < typename ReturnType, typename ParamType > class ClassB<ReturnType (*)(ParamType)> { public: template < ReturnType (*Func)(ParamType) > void TestMe() { } }; void SomeFunction(int) { } void TestCase() { ClassA<void, int> A; A.TestMe<SomeFunction>(); ClassB<void (*)(int)> B; // error C2440: 'specialization' : cannot convert from 'void (__cdecl *)(int)' to 'ReturnType (__cdecl *const )(ParamType)' B.TestMe<SomeFunction>(); }
Thanks in advance for any help given! :)
Alice
回答
Seems to be a problem of older compiler, which is fixed in Visual Studio 2008.
Try adding ‘const’ after ‘*’ in some of declarations. For possible workarounds see:
· http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0ba8dde0-58d2-4e43-aff0-38a2b9eaab2f
· http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/e4b59901-6bec-4560-9e7c-9e89c20c3985.
- 回答としてマークblueberryblush 2009年11月4日 16:01
すべての返信
Seems to be a problem of older compiler, which is fixed in Visual Studio 2008.
Try adding ‘const’ after ‘*’ in some of declarations. For possible workarounds see:
· http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0ba8dde0-58d2-4e43-aff0-38a2b9eaab2f
· http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/e4b59901-6bec-4560-9e7c-9e89c20c3985.
- 回答としてマークblueberryblush 2009年11月4日 16:01
- Thanks.
The links you gave me were interesting, particularly the second one, which highlights my problem. I found the bug report though (https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=251467 ), and the last thing said was "The fix will show up in the next release of Visual C++", refering to versions after SP1; which suggests the issue would be fixed in SP2. I'm not sure what version I have but I'm having difficulty locating service pack 2.
Anyway. I've used a similar workaround to that found in the bug report.
I will mark your post as an answer as it seems that the only solution to this is to use a workaround - or to drop support for VC2005; which I'd rather not do.
Thanks for your time :)
Alice
EDIT - To clarify for anyone else with a similar problem, here is my workaround. It is basically the same as the workaround found in the bug report.
I have renamed the classes involved so that they are more relevant to the typical application.
// Forward declarations template < typename T > class Delegate; template < typename ReturnType, typename ParamType > class Helper; // Our delegate class (only partially implemented to address the main issue) template < typename ReturnType, typename ParamType > class Delegate<ReturnType (*)(ParamType)> { public: typedef Helper<ReturnType, ParamType> Binder; // Stored function pointer ReturnType (*Func_)(ParamType); }; // Helper class - binds the function without using template specialisation (avoids the C2440 error in VC2005) template < typename ReturnType, typename ParamType > class Helper { public: template < ReturnType (*Func)(ParamType) > static Delegate<ReturnType (*)(ParamType)> Bind() { Delegate<ReturnType (*)(ParamType)> D; D.Func_ = Func; return D; } }; void SomeFunction(int { } void TestCase() { Delegate<void (*)(int)> Test = Delegate<void (*)(int)>::Binder::Bind<SomeFunction>(); }

