Подстановка пустоты как параметра в шаблонный метод
В моем коде у меня есть класс, который регистрирует методы других классов:
#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;
}
Раскомментированная строка /* 2 */ выдает ошибку:
Сбой вывода / замены аргумента шаблона:
При замене 'шаблона void register_f(std::string, R (C::*)(A)) [с R = R; A = A; C = A] [с R = int; A = void] ':
ошибка: неверный тип параметра 'void'
Строка / * 1 / совпадает с / 2 * /, но с не очень информативным сообщением об ошибке.
Я понимаю, что для решения проблемы я могу использовать метод register_void_f, но я не хочу этого делать, потому что register_f является частью моего окончательного API.
Вопрос> Как исправить ошибки компиляции, не вводя register_void_f?
У меня есть идея решить эту проблему с помощью частичного специализированного register_f, но я не знаю, как это сделать, поскольку в C++ нельзя частично специализировать шаблонный метод.
PS> Я не могу использовать C++11.
3 ответа
Перегрузите вашу функцию:
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);
}
Преобразование этого в методы должно быть простым.
Не использовать void
без аргументов ничего не используйте - как-то так:
template< typename R>
void register_void_f( string name, R ( C:: *method_p ) ()) { /*registration process*/ }
Вы можете использовать следующее:
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);