2014-09-22 97 views
6

在我的代码我有注册其他类别的方法的一类:替代无效的作为参数传递给模板方法

#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

取消注释行/ * 2 * /给我一个错误:

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’

线/ * 1 /相同/ 2 * /,但并非如此信息的错误消息。

我明白,要解决我可以使用方法register_void_f的问题,但我不想这样做,因为register_f是我最后的API的一部分。

问题>如何解决编译错误而不引入register_void_f

我有一个想法解决它与部分专业register_f,但我不知道该怎么做,因为在C++中,你不能部分专门化模板方法。

PS>我不能使用C++ 11。

回答

2

超载的功能:

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

转换这是它方法应该很容易。

+0

谢谢雅克,奇怪的是它有效! http://ideone.com/Jk3NOp – 2014-09-22 14:26:51

+0

我认为这将很难专业化。 – 2014-09-22 14:27:38

+0

@ValentinT。重写不是专业化。专业化是不同的,并且*通常*与功能不好的想法(你最好重写)。如果你需要花哨的专业化,你通常会转向一门专业机械课程,而不是专业化的功能模板。 – Yakk 2014-09-22 14:32:34

3

不要使用void对于没有参数,使用什么 - 这样的事情:

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

的问题是如何做到这一点不** ** register_void_f。我认为使用或不**无效**没有区别。 – 2014-09-22 14:14:51

+0

如何使用不带参数的版本重载'register_f'? – Alex 2014-09-22 14:17:53

+0

使用继承,你的意思是? – 2014-09-22 14:23:28

2

您可以使用以下方法:

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*/ } 

    }; 

而使用它的方式:

Reg< A> r; 

r.register_f("g", &A::g); 
r.register_f("f", &A::f); 
r.register_f<int (A::*)(void)>("f", &A::f); 
相关问题