boost::enable_if, did I get it wrong ?

Hello, I'm trying to use boost::enable_if to customize function declaration for a particular set of template arguments. But instead of using SFINAE to remove incorrect declaration it produces error. See the example below to see better what I mean: #include <boost/utility.hpp> #include <boost/type_traits.hpp> template<class A, class B> struct BaseListener { typename boost::disable_if<boost::is_void< B >, void>::type void virtual process(A *, B *) = 0; typename boost::enable_if<boost::is_void< B >, void>::type void virtual process(A *) = 0; }; struct Request { }; struct Response { }; typedef BaseListener<Response, void> BaseResponseListener; typedef BaseListener<Request, BaseResponseListener> BaseRequestListener; struct RequestListener : public BaseRequestListener { void process(Request *, BaseResponseListener *) { } }; struct ResponseListener : public BaseResponseListener { void process(Request *) { } }; int main(int argc, char * argv[]) { RequestListener reqListener; ResponseListener resListener; return 0; } error message: error C2039: 'type' : is not a member of 'boost::enable_if<Cond,T>' 1> with 1> [ 1> Cond=boost::is_void<BaseResponseListener>, 1> T=void 1> ] 1> c:\!projects\temp\consoleeventhandler\consoleeventhandler.cpp(134) : see reference to class template instantiation 'BaseListener<A,B>' being compiled 1> with 1> [ 1> A=Request, 1> B=BaseResponseListener 1> ] -- View this message in context: http://www.nabble.com/boost%3A%3Aenable_if%2C-did-I-get-it-wrong---tp2502791... Sent from the Boost - Users mailing list archive at Nabble.com.

You can only apply enable_if to template arguments of the function and not of the class which contains the function, but you can't declare a virtual function template... So this is your dilemma. Regards, Ovanes On Tue, Aug 18, 2009 at 7:23 PM, topoden <_dvt_@mail.ru> wrote:
Hello,
I'm trying to use boost::enable_if to customize function declaration for a particular set of template arguments. But instead of using SFINAE to remove incorrect declaration it produces error. See the example below to see better what I mean:
#include <boost/utility.hpp> #include <boost/type_traits.hpp>
template<class A, class B> struct BaseListener { typename boost::disable_if<boost::is_void< B >, void>::type void virtual process(A *, B *) = 0;
typename boost::enable_if<boost::is_void< B >, void>::type void virtual process(A *) = 0; };
struct Request { };
struct Response { };
typedef BaseListener<Response, void> BaseResponseListener; typedef BaseListener<Request, BaseResponseListener> BaseRequestListener;
struct RequestListener : public BaseRequestListener { void process(Request *, BaseResponseListener *) { } };
struct ResponseListener : public BaseResponseListener { void process(Request *) { } };
int main(int argc, char * argv[]) { RequestListener reqListener; ResponseListener resListener;
return 0; }
error message: error C2039: 'type' : is not a member of 'boost::enable_if<Cond,T>' 1> with 1> [ 1> Cond=boost::is_void<BaseResponseListener>, 1> T=void 1> ] 1> c:\!projects\temp\consoleeventhandler\consoleeventhandler.cpp(134) : see reference to class template instantiation 'BaseListener<A,B>' being compiled 1> with 1> [ 1> A=Request, 1> B=BaseResponseListener 1> ] -- View this message in context: http://www.nabble.com/boost%3A%3Aenable_if%2C-did-I-get-it-wrong---tp2502791... Sent from the Boost - Users mailing list archive at Nabble.com.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Just another note, what is that suppose to be? typename boost::disable_if<boost::is_void< B >, void>::type
void virtual process(A *, B *) = 0;
It is not a return value or template argument. I hope I got right in the previous post what you were going to do, and said that it is not supported. On Tue, Aug 18, 2009 at 8:21 PM, Ovanes Markarian <om_boost@keywallet.com>wrote:
You can only apply enable_if to template arguments of the function and not of the class which contains the function, but you can't declare a virtual function template... So this is your dilemma.
Regards, Ovanes
On Tue, Aug 18, 2009 at 7:23 PM, topoden <_dvt_@mail.ru> wrote:
template<class A, class B> struct BaseListener { typename boost::disable_if<boost::is_void< B >, void>::type void virtual process(A *, B *) = 0;
typename boost::enable_if<boost::is_void< B >, void>::type void virtual process(A *) = 0; };

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 18 August 2009, topoden wrote:
Hello,
I'm trying to use boost::enable_if to customize function declaration for a particular set of template arguments. But instead of using SFINAE to remove incorrect declaration it produces error.
What you are doing is an error (and not just the extra void you have in the return types). SFINAE drops template functions from consideration during overload resolution. You would need to make the process member functions templates (but you can't because there are no virtual template methods in C++). It looks like what you are trying to do is provide a partial template specialization of BaseListener when the second template parameter is void.
template<class A, class B> struct BaseListener { typename boost::disable_if<boost::is_void< B >, void>::type void virtual process(A *, B *) = 0;
typename boost::enable_if<boost::is_void< B >, void>::type void virtual process(A *) = 0; }; -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux)
iEYEARECAAYFAkqK8jYACgkQ5vihyNWuA4X6EQCghDjl2cK4DNnny0rVa4Y0pANG pQYAniT1sOhdA2nDKbJysoGBDuIKzaU/ =2eVR -----END PGP SIGNATURE-----

Guys, You were right, the extra "void" is incorrect in the code (sorry for the mistake), but you got the idea right. I basically want to "partially specialize the template class for the case when the second template argument is "void"" I did not want to do the specialization "manually" because the actual template class is quite long, and there is lot of stuff which depends on the second template argument but the only code which should be different is this virtual method declaration. So specializing it manually would double up the amount of code. So I thought I could use boost::enable_if, but this looks now that its not the case... Thanks a lot for your help guys. -- View this message in context: http://www.nabble.com/boost%3A%3Aenable_if%2C-did-I-get-it-wrong---tp2502791... Sent from the Boost - Users mailing list archive at Nabble.com.

topoden wrote:
Guys,
You were right, the extra "void" is incorrect in the code (sorry for the mistake), but you got the idea right. I basically want to "partially specialize the template class for the case when the second template argument is "void""
I did not want to do the specialization "manually" because the actual template class is quite long, and there is lot of stuff which depends on the second template argument but the only code which should be different is this virtual method declaration. So specializing it manually would double up the amount of code.
You could have a newly created base class template specializations to contain either of those virtual functions, unless I'm missing something. Just specialize that base class template partially for B = void case and make BaseListener<> inherit from ProcessBase< A, B > (or whatever you name it). HTH, Gevorg
participants (4)
-
Frank Mori Hess
-
Gevorg Voskanyan
-
Ovanes Markarian
-
topoden