C ++ Template + Iterator (Nob question)

My mention is that I started teaching C ++ about a week ago and my previous programming experience was with dynamic languages ​​(Python, javascript).

I am trying to iterate through the contents of a Vector using a generic function to print out the elements:

#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 won't compile. Can anyone explain why?

Edit: 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>)'

Thank!

+2


source to share


4 answers


Try:

for_each(myV.begin(), myV.end(), p<int>);

      

There were two errors in your code:

  • Iterators were not of the same type
  • The function pointer was not actually a pointer.
    • Typically, template functions can be inferred from parameters. But in this case, you are not actually using it, you are passing it (or its address) to the function (and the normal inference rules of the template function do not work). Since the compiler cannot determine which version of the "p" function you want to use, you must be explicit.

There is also a nice inference iterator that does this:



std::copy(myV.begin(),myV.end(), std::ostream_iterator<int>(std::cout));

      

Also note that very few compilers can optimize your code by calling a function pointer.
Although most of them can optimize the call if it's a functor object. So the following is 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 using templated methods / functions, it is usually better to pass a const value than a value. If the type is expensive to copy, then passing by value will create a copy, which may not be what you expected.

+13


source


The reason Martin's solution works and yours doesn't is because p

it is a function template, not an actual function. The template function does not have an address that you can take, or jump to the function. You have to instantiate the template function in order to create the actual function that you can use.



+3


source


The problem is that you need to pass some "callable" to std::for_each

. It can be a function object (that the class overloads the function call operator) or a function pointer. (Where a function pointer is needed, you can pass a function name with an appropriate prototype - function names are implicitly converted to function addresses.)

However, yours is p

not a function, it is a function template. And a function template is simple: a template for creating functions from. You need to pass such a generated function instead of the template name. The mechanism that allows the compiler to create a function from a function template is often referred to as instantiation. Therefore, you need an instance of the template. This is implicitly generated by the compiler whenever you use such an instance.

So, as others have said, you need to explicitly pass p<int>

to std::foreach

:

std::for_each(myV.begin(), myV.end(), p<int>);

      

+1


source


I haven't used for_each in C ++, but I would write the same loop like this:

vector <int> :: iterator iter;

for (iter = myV.begin (); iter! = myV.end (); iter ++) {
    p (iter);
}
0


source







All Articles