与宏的模板功能 - 在传染媒介上积累 [英] Template function with macro - accumulate on vector

查看:150
本文介绍了与宏的模板功能 - 在传染媒介上积累的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个函数来获得 vector< int> 运行所有的元素,并根据我选择的具体操作符sum他们。 b
$ b

例如, 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>
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<< 遍历所有具有*的向量是:< allVectorWithOperator(myVector,*)<<< endl;
//这里我想得到3 * 6 * 7

}


$ b b

我在这种情况下模板不能很好地控制,所以你可以看到这个代码不工作,但我想你明白我的目标是什么。我如何解决它工作正常?



编辑:



到 -

  #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<< 累加具有*的向量是:
< allVectorWhitOperator(myVector,std :: multiplies< int>())<< endl

}

确实I 累积了具有*的向量是:72

解决方案

a href =http://en.cppreference.com/w/cpp/algorithm/accumulate =nofollow>这基本上只是 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. 一个 * t是有效的语法。但是C ++提供了很多函数对象,它们包装这些运算符,以便您可以使用它们与函数符号。例如,

      std :: multiplies< int> F; // f是一个现在函数,它将2个数字相乘
    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));
    }
    }

    此外,还有一些小问题:比较迭代器与!= 而不是< = ,因为许多迭代器不支持< = 运算符,(2) ++ 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; \
    }())

    b
    $ b

    是的,这是一个完整的混乱,所以你应该更喜欢不使用宏,如果可能的话。 BTW, #OP 表示将 OP 变成字符串。你真的不需要



I want to create a function that get vector<int> run over all his elements and "sum" them according to specific operator I chose .

For example , v1 = [3,6,7] so I could calculate by this function - 3+6+7 of 3-6-7 of 3*6*7 etc ..

For this I did -

#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    

}

I don't control very well in such cases of template so as you can see this code doesn't work, but I think you understand what is my goal. How can I fix it to work fine?

Edit:

according the 2 answer I got I changed the code section to -

#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;

}

And it work fine ! indeed I got accumulate the vector with * is :72

解决方案

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 #.

这篇关于与宏的模板功能 - 在传染媒介上积累的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆