My disclaimer here is that I started teaching myself C++ about a week ago and my former experience with programming has been with dynamic languages (Python, javascript).
I'm trying to iterate though the contents of a vector using a generic function to print out the items:
#include <iostream>
#include <algorithm>
#include <vector>
using std::vector;
using std::cout;
template <class T>
void p(T x){
cout << x;
}
int main () {
vector<int> myV;
for(int i = 0; i < 10; i++){
myV.push_back(i);
}
vector<int>开发者_开发百科::const_iterator iter = myV.begin();
for_each(iter, myV.end(), p);
return 0;
}
The code doesn't compile. Would someone explain why?
Edit: The compiler error:
error: no matching function for call to 'for_each(_gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<const int, _gnu_norm::vector<int, std::allocator<int> > >, __gnu_debug_def::vector<int, std::allocator<int> > >&, __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int, __gnu_norm::vector<int, std::allocator<int> > >, __gnu_debug_def::vector<int, std::allocator<int> > >, <unknown type>)'
Thanks!
Try:
for_each(myV.begin(), myV.end(), p<int>);
There were two mistakes in your code:
- The iterators were not the same type
- The function pointer was not actually a pointer.
- Normally templated functions can be deduced from there parameters. But in this case you are not actually using it you are passing it (or its address) to a function (thus the normal rules on template function deduction did not work). As the compiler can not deduce which version of the function 'p' you need to use you must be explicit.
There is also a nice output iterator that does this:
std::copy(myV.begin(),myV.end(), std::ostream_iterator<int>(std::cout));
Also note that very few compilers can optimise code across a function pointer call.
Though most are able to optimise the call if it is an functor object. Thus the following may have been a viable alternative to a function pointer:
template<typename T>
struct P
{
void operator()(T const& value) const
{
std::cout << value;
}
};
....
for_each(myV.begin(), myV.end(), P<int>());
Another note:
When you use templated methods/functions it is usually better to pass by const reference than value. If the Type is expensive to copy then passing by value will generate a copy construction which may not be what you expected.
The reason that Martin's solution works and yours doesn't is that p
is a function template, and not an actual function. A template function doesn't have an address that you can take, or pass to a function. You have to instantiate a template function, to create an actual function you can use.
You problem is that you have to pass some "callable entity" to std::for_each
. That could be a function object (that's a class overloading the function call operator) or a function pointer. (Wherever a function pointer is needed you can pass in the name of a function with a matching prototype - functions names implicitly convert into function addresses.)
However, your p
isn't a function, it's a function template. And a function template is just that: a template to create functions from. You need to pass such a created function instead of the template's name. The mechanism to let the compiler create a function from a function template is often called template instantiation. So you need an instance of the template. That is created by the compiler implicitly whenever you use such an instance.
So, as others have already said, you need to explicitly pass p<int>
to std::foreach
:
std::for_each(myV.begin(), myV.end(), p<int>);
I haven't used for_each in C++, but I would write same cycle so:
vector<int>::iterator iter; for(iter = myV.begin(); iter != myV.end(); iter++) { p(iter); }
精彩评论