Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Substitution of void as parameter to templated method

In my code I have a class which registers method's 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

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

template argument deduction/substitution failed:

In substitution of ‘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’

Line /* 1 / is the same as / 2 */, but with not so informative error message.

I understand that to fix the problem I can use method register_void_f, but I don't want to do it because register_f is a part of the my final API.

Question> How to fix the compilation errors without introducing register_void_f?

I have an idea to solve it with partial specialized register_f, but I don't know how to do it since in C++ you can't partially specialize templated method.

PS> I can't use C++11.

like image 569
Valentin T. Avatar asked Sep 22 '14 14:09

Valentin T.


2 Answers

Don't use void for no arguments, use nothing - something like this:

template< typename R>
     void register_void_f( string name, R ( C:: *method_p ) ()) { /*registration process*/ }
like image 68
Paul Evans Avatar answered Nov 11 '22 05:11

Paul Evans


Overload your function:

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);
}

live example

Converting this to it being methods should be easy.

like image 2
Yakk - Adam Nevraumont Avatar answered Nov 11 '22 05:11

Yakk - Adam Nevraumont