Replacing void as a parameter with a template method

In my code, I have a class that registers the method of other classes:

#include <iostream> using namespace std; template< typename C> class Reg { public: template< typename R, typename A> void register_f( string name, R ( C:: *method_p ) ( A)) { /*registration process*/ } // template< typename R> // void register_void_f( string name, R ( C:: *method_p ) ( void)) { /*registration process*/ } }; class A { public: int f( void) { return 1; } void g( int x) { /* some code*/ } }; int main() { Reg< A> r; r.register_f( "g", &A::g); /*1*/// r.register_f( "f", &A::f); /*2*/// r.register_f< int, void>( "f", &A::f); /*3*/// r.register_void_f< int>( "f", &A::f); return 0; } 

http://ideone.com/X8PNLC

Invalid line / * 2 * / gives me an error:

Error outputting template argument:

In the substitution 'template void register_f (std :: string, R (C :: *) (A)) [with R = R; A = A; C = A] [with R = int; A = void]:

error: invalid parameter type 'void

The line / * 1 / matches with / 2 * /, but with a not-so-informative error message.

I understand that I can use the register_void_f method to fix the problem, but I do not want to do this because register_f is part of my final API.

Questions> How to fix compilation errors without register_void_f ?

I have an idea to solve it with a partial specialized register_f , but I donโ€™t know how to do it, since in C ++ you cannot partially specialize a template method.

PS> I can not use C ++ 11.

+6
source share
3 answers

Function overload:

 void foo( int ) {} double bar() { return 3.14; } template< class R, class A > void test( R ( *method_p ) (A)) { } template< class R > void test( R ( *method_p ) ()) { } int main(){ test(foo); test(bar); } 

living example

Converting this method to it should be easy.

+2
source

Do not use void without arguments, do not use anything - something like this:

 template< typename R> void register_void_f( string name, R ( C:: *method_p ) ()) { /*registration process*/ } 
+3
source

You can use the following:

 template< typename C> class Reg; template <typename C, typename F> struct helper; template <typename C, typename R, typename A> struct helper<C, R (C::*)(A)> { void operator() (Reg<C>& reg, const std::string& name, R (C::*method)(A)) const { /* Your implementation */} }; template <typename C, typename R> struct helper<C, R (C::*)()> { void operator() (Reg<C>& reg, const std::string& name, R (C::*method)()) const { /* Your implementation */} }; template< typename C> class Reg { public: template< typename F> void register_f(const std::string& name, F method) { helper<C, F>()(*this, name, method); /*registration process*/ } }; 

And use it like this:

 Reg< A> r; r.register_f( "g", &A::g); r.register_f( "f", &A::f); r.register_f<int (A::*)(void)>( "f", &A::f); 
+2
source

Source: https://habr.com/ru/post/975652/


All Articles