Функция шаблона с макросом — накапливается на векторе

Я хочу создать функцию, которая получит vector<int> выполнить все его элементы и «сложить» их в соответствии с выбранным оператором.

Например , v1 = [3,6,7] чтобы я мог рассчитать по этой функции — 3+6+7 из 3-6-7 из 3*6*7 так далее ..

Для этого я сделал —

#include <iostream>
#include <vector>

using namespace std;

#define     OPERATOR(X,Y,OP)  X #OP Y

template<T>
int allVectorWithOperator(vector<int> &myVector, T) {
vector<int>::iterator it;
vector<int>::iterator oneBeforeFinal;
oneBeforeFinal = myVector.end();
oneBeforeFinal -= 2;
int sum = 0;
for (it = myVector.begin(); it <= oneBeforeFinal; it++) {
sum = OPERATOR(*(it),*(it+1),T);
}
return sum;

}

int main() {
vector<int> myVector;
myVector.push_back(3);
myVector.push_back(6);
myVector.push_back(7);
cout << "run over all the vector with * is :" << allVectorWithOperator(myVector,*)<<endl;
// here I want to get 3*6*7

}

Я не очень хорошо контролирую в таких случаях шаблоны, так как вы можете видеть, что этот код не работает, но я думаю, вы понимаете, какова моя цель. Как я могу исправить это, чтобы работать нормально?

Редактировать:

в соответствии с ответом 2, который я получил, я изменил раздел кода на —

#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

template<typename T>
int allVectorWhitOperator(vector<int> &myVector, const T& func) {
int sum = std::accumulate(myVector.begin(), myVector.end(), 1, func);
return sum;

}

int main() {
vector<int> myVector;
myVector.push_back(3);
myVector.push_back(4);
myVector.push_back(6);
cout << "accumulate the vector with * is :"<< allVectorWhitOperator(myVector, std::multiplies<int>()) << endl;

}

И это работает нормально! действительно я got accumulate the vector with * is :72

2

Решение

Это в основном просто std::accumulate. Предполагая, что вектор не пустой, вы можете переписать функцию следующим образом:

template <typename C, typename F>
typename C::value_type fold(const C& container, const F& function) {
typename C::iterator cur = container.begin();
typename C::value_type init = *cur++;
return std::accumulate(cur, container.end(), init, function);
}

...

int sum = fold(myVector, std::plus<int>());
int difference = fold(myVector, std::minus<int>());
int product = fold(myVector, std::multiplies<int>());

Теперь о вашей реализации:

  1. Как показано в примере выше, чтобы объявить параметр типа в шаблоне, вам нужно иметь typename или же class ключевое слово: template <typename T> int allVectorWithOperator( ... )

  2. В одиночестве * не будет действительным синтаксисом. Но C ++ предоставляет множество «функциональных объектов», которые обслуживают эти операторы, чтобы вы могли использовать их с обозначениями функций. Например,

    std::multiplies<int> f; // f is a now function that multiplies 2 numbers
    int product = f(5, 7);  // p == 35;
    

    чтобы вы могли написать:

    template<typename T>
    int allVectorWithOperator(vector<int> &myVector, T func) {
    ....
    for (it = myVector.begin(); it != oneBeforeFinal; ++ it) {
    sum = func(*it, *(it+1));
    }
    }
    

    Кроме того, некоторые незначительные моменты: (1) Обычно мы сравниваем итераторы с != вместо <=потому что многие итераторы не поддерживают <= оператор, (2) ++it более эффективен, чем it++ в общем.

  3. Макросы и шаблоны обрабатываются на разных этапах. В частности, вы не можете передать шаблон или параметр функции в макрос, потому что все макросы уже оцениваются при рассмотрении шаблонов. Чтобы добиться вашего синтаксиса, весь allVectorWithOperator должен быть написан как макрос, например (при условии использования C ++ 11):

    #define allVectorWithOperator(container, binaryOp) \
    ([&]() -> std::remove_reference<decltype(*(container).begin())>::type { \
    auto&& c = (container); \
    auto cur = c.begin(); \
    auto val = *cur++; \
    auto end = c.end(); \
    while (cur != end) { val binaryOp##= *cur++; } \
    return val; \
    }())
    

    Да, это полный беспорядок, поэтому вы должны предпочесть не использовать макросы, если это возможно. КСТАТИ, #OP означает поворот OP в строку. Вам не нужно #,

4

Другие решения

Стандартная библиотека уже имеет операции в <algorithm><numeric>,

Ты можешь использовать

int sum = std::accumulate(MyVector.begin(), MyVector.end(), 0);

сложить все элементы.

Если вы хотите вычислить продукт (вместо использования по умолчанию operator+), вы можете передать дополнительный параметр

int product = std::accumulate(MyVector.begin(), MyVector.end(), 1,
std::multiplies<int>());
7