Добрый день.
Я уже задавал похожий вопрос вот ссылка на мой старый вопрос, и снова он возник.
Итак, есть код:
#define OPERATIONWRAPPER(name) \
void name(ob_savewrapper* a){ \
var* tmpptr=ptr->name##_v(a->ptr); \
if(tmpptr==ptr){ a->clear();} else {clear();transfer(a);} \
}
//some realization
class savewrapper {
var* ptr;
public:
savewrapper() :ptr(NULL) {}
savewrapper(var* p) :ptr(p) {}
void setptr(var* s) {
if ((ptr != NULL) && (s != NULL)) {
clear();//for eliminate double delete
ERR(ob_err78)
}//if
ptr = s;
}
void clear() { delete ptr; ptr = NULL; }
~savewrapper() { delete ptr; }
void transfer(savewrapper* d) {
setptr(d->ptr);
d->setptr(NULL);
}
OPERATIONWRAPPER(add);
OPERATIONWRAPPER(sub);
OPERATIONWRAPPER(mul);
OPERATIONWRAPPER(div);
OPERATIONWRAPPER(pww);
};
Здесь есть иерархия классов, в которой класс var является базовым. Класс savewrapper это обертка над классами этой иерархии. В классах иерархии есть функции add_v, sub_v, mul_v, div_v, pww_v. В классе savewrapper должны быть функции add, sub, mul, div, pww, в которых вызываются соответствующие функции из классов иерархии var.
Сейчас это сделано через макрос, как видно в примере. Но я хочу быть передовым программистом, и поэтому я решил переделать макрос в шаблон. Пишу шаблон:
template<var* (var::*method)(var* ptr1)> inline void operation_wrapper(savewrapper* a) {
var* tmpptr = (ptr->*method)(a->ptr);
if (tmpptr == ptr) {
a->clear();
}
else {
clear();
transfer(a);
}
}
Инстанцирую шаблон для примера для метода add:
void add(savewrapper* a) { operation_wrapper<&(var::add_v)>(a); }
Все даже работает, но есть лишний вызов по сравнению с решением на основе макроса. А именно, хотя шаблон объявлен как inline, но инлайн не гарантируется компилятором. А если шаблон будет не инлайн, то будет лишний вызов функции, по сравнению с решением на основе макроса.
Вопрос:
Как сделать так, чтобы не было лишнего вызова функции? Имя add для метода класса savewrapper должно сохраниться, так как во многих местах оно используется и подставлять по всему коду вместо add явный вызов шаблона
operation_wrapper<&(var::add_v)>(a);
это очень плохой вариант.
Спасибо.
UPD1:
Вобщем, как не крути, но получается что для шаблонов функций нужно иметь еще одну возможность. А именно, при инстанцировании шаблона функции нужно иметь возможность дать получившейся функции новое имя. Иначе шаблоны проигрывают по гибкости макросам.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей