与宏的模板功能 - 在传染媒介上积累 [英] Template function with macro - accumulate on vector
问题描述
我想创建一个函数来获得 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>());
现在,
如上面的示例所示,要在模板中声明一个类型参数,您需要使用
typename
或class
关键字:template< typename T> int allVectorWithOperator(...)
一个
*
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
比
宏和模板在不同的阶段进行处理。特别是,您无法将模板或函数参数传递给宏,因为所有宏都已在考虑模板时进行评估。要实现你的语法,整个
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
of3-6-7
of3*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:
As shown in the example above, to declare a type parameter in the template, you need to have the
typename
orclass
keyword:template <typename T> int allVectorWithOperator( ... )
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 thanit++
in general.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 theOP
into a string. You don't really need the#
.
这篇关于与宏的模板功能 - 在传染媒介上积累的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!