2014-09-22 22 views
6

Trong mã của tôi, tôi có một lớp học mà đăng ký phương pháp của các lớp khác:Thay void như tham số để phương pháp templated

#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

dòng uncommenting/* 2 */mang lại cho tôi một lỗi:

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’

Dòng/* 1 /giống như/ 2 * /, nhưng không có thông báo lỗi mang tính thông tin.

Tôi hiểu rằng để khắc phục vấn đề tôi có thể sử dụng phương pháp register_void_f, nhưng tôi không muốn làm điều đó vì register_f là một phần của API cuối cùng của tôi.

Câu hỏi> Cách sửa lỗi biên dịch mà không cần giới thiệu register_void_f?

Tôi có một ý tưởng để giải quyết nó với một phần chuyên biệt register_f, nhưng tôi không biết làm thế nào để làm điều đó vì trong C++ bạn không thể chuyên về một phần phương pháp templated.

PS> Tôi không thể sử dụng C++ 11.

Trả lời

2

quá tải chức năng của bạn:

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

Chuyển đổi này để nó là phương pháp nên dễ dàng.

+0

Cảm ơn bạn Yakk, kỳ lạ nó hoạt động! http://ideone.com/Jk3NOp –

+0

Tôi nghĩ thật khó để chuyên môn hóa nó. –

+0

@ValentinT. ghi đè không phải là chuyên môn hóa. Chuyên môn là khác nhau, và * thường là một ý tưởng tồi với các chức năng (bạn nên ghi đè tốt hơn). Nếu bạn cần chuyên môn hóa ưa thích, bạn thường chuyển tiếp đến một lớp học mà bạn có đầy đủ về máy móc chuyên môn hóa, và không phải là chuyên môn về chức năng làm tê liệt và bối rối. – Yakk

3

Không sử dụng void cho không có đối số, sử dụng - một cái gì đó như thế này:

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

Vấn đề là làm thế nào để làm điều đó mà không ** register_void_f **. Tôi nghĩ rằng việc sử dụng hay không ** void ** không có sự khác biệt. –

+0

làm thế nào về quá tải 'register_f' với một phiên bản mà không có tham số? – Alex

+0

sử dụng thừa kế, ý của bạn là gì? –

2

Bạn có thể sử dụng như sau:

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

    }; 

Và sử dụng nó như vậy:

Reg< A> r; 

r.register_f("g", &A::g); 
r.register_f("f", &A::f); 
r.register_f<int (A::*)(void)>("f", &A::f); 
Các vấn đề liên quan