Как в С++ вызвать шаблонную функцию напрямую? [продолжение]

218
21 февраля 2018, 11:04

Добрый день.

Я уже задавал похожий вопрос вот ссылка на мой старый вопрос, и снова он возник.

Итак, есть код:

#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, но инлайн не гарантируется компилятором. А если шаблон будет не инлайн, то будет лишний вызов функции, по сравнению с решением на основе макроса.

Вопрос:

  1. Как сделать так, чтобы не было лишнего вызова функции? Имя add для метода класса savewrapper должно сохраниться, так как во многих местах оно используется и подставлять по всему коду вместо add явный вызов шаблона

    operation_wrapper<&(var::add_v)>(a);

это очень плохой вариант.

Спасибо.

UPD1:

Вобщем, как не крути, но получается что для шаблонов функций нужно иметь еще одну возможность. А именно, при инстанцировании шаблона функции нужно иметь возможность дать получившейся функции новое имя. Иначе шаблоны проигрывают по гибкости макросам.

READ ALSO
древовидная структура данных

древовидная структура данных

С помощью каких инструментов можно реализовать древовидную структуру? Иерархическая модель компании: допустим есть 1 начальник, 3 менеджера...

211
Удаление блоков элементов

Удаление блоков элементов

Создать функцию, позволяющую удалять блок элементов произвольного размера, начиная с произвольного индекса массиваЛюди объясните пожалуйста...

210
запрет нажатия QPushButton дважды Qt / C++

запрет нажатия QPushButton дважды Qt / C++

создаю калькулятор и надо запретить нажатие QPushButton кнопки дважды по очереди например ++ // или например запретить кнопку = нажимать дважды

233
Не могу перегрузить оператор &ldquo;&lt;&rdquo; для класса

Не могу перегрузить оператор “<” для класса

Необходимости засовывать оператор в класс не былоНаоборот, правильнее перегружать такой оператор отдельной функцией

306