【问题标题】:Template function with macro - accumulate on vector带有宏的模板函数-在向量上累积
【发布时间】:2012-08-30 13:07:05
【问题描述】:

我想创建一个函数,让vector<int> 遍历他的所有元素并根据我选择的特定运算符“求和”它们。

例如,v1 = [3,6,7] 所以我可以通过这个函数计算 - 3+6+73-6-73*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

【问题讨论】:

    标签: c++ templates vector macros c-preprocessor


    【解决方案1】:

    标准库中已有&lt;algorithm&gt;&lt;numeric&gt;中的操作。

    你可以使用

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

    将所有元素相加。

    如果你想计算乘积(而不是使用默认的operator+),你可以传递一个额外的参数

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

    【讨论】:

    • 是的,它们来自原始标准。
    • 我想你的意思是std::accumulate(MyVector.begin(), MyVector.end(), 1, std::multiplies&lt;int&gt;());
    【解决方案2】:

    This is basically just 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. 如上例所示,要在模板中声明类型参数,需要有typenameclass关键字:template &lt;typename T&gt; 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)通常我们将迭代器与!=而不是&lt;=进行比较,因为许多迭代器不支持&lt;=运算符,(2)++it比@更有效987654334@一般。

    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 变成一个字符串。你真的不需要#

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      • 2018-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多