Template function with macro - accumulate on vector

喜你入骨 提交于 2019-12-06 05:27:15

This is basically just std::accumulate. Assuming the vector is not empty, you could rewrite the function as:

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>());

Now, about your implementation:

  1. As shown in the example above, to declare a type parameter in the template, you need to have the typename or class keyword: template <typename T> int allVectorWithOperator( ... )

  2. A lone * won't be a valid syntax. But C++ provides a lot of "function objects" which serve wraps these operators so that you could use them with the function notation. For example,

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

    so you could write:

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

    Also, some minor points: (1) Usually we compare iterators with != instead of <=, because many iterators don't support the <= operator, (2) ++it is more efficient than it++ in general.

  3. Macros and templates are processed in different stages. In particular, you can't pass a template or function parameter to a macro, because all macros are already evaluated when templates are considered. To achieve your syntax, the whole allVectorWithOperator must be written as a macro, e.g. (assuming C++11 can be used):

    #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; \
        }())
    

    Yes it's a complete mess, so you should prefer not to use macros if possible. BTW, #OP means turning the OP into a string. You don't really need the #.

The standard library already has the operations in <algorithm><numeric>.

You can use

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

to add up all the elements.

If you want to compute the product (instead of using the default operator+), you can pass an additional parameter

int product = std::accumulate(MyVector.begin(), MyVector.end(), 1,
                              std::multiplies<int>());
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!