Passing a function pointer as a template parameter

For educational purposes, I'm trying to write my own "ForEach" function:

#include <iostream>
#include <string>
#include <vector>


//
// This works
//
template<class Container>
void ForEach_v1(const Container & inContainer, void (*Functor)(const std::string &))
{
    typename Container::const_iterator it = inContainer.begin(), end = inContainer.end();
    for (; it != end; ++it)
    {
        Functor(*it);
    }
}


//
// Does not work
//
template<class Container, class Functor>
void ForEach_v2(const Container & inContainer, Functor inFunctor)
{
    typename Container::const_iterator it = inContainer.begin(), end = inContainer.end();
    for (; it != end; ++it)
    {
        Functor(*it);
    }
}

void PrintWord(const std::string & inMessage)
{
    std::cout << inMessage << std::endl;
}

int main()
{
    std::vector<std::string> words;
    words.push_back("one");
    words.push_back("two");
    words.push_back("three");

    // Works fine.
    std::cout << "v1" << std::endl;
    ForEach_v1(words, PrintWord);

    // Doesn't work.
    std::cout << "v2" << std::endl;
    ForEach_v2(words, PrintWord);

    return 0;
}

Compiler Output:

|| g++ -Wall -o test main.cpp
|| main.cpp: In function 'void ForEach_v2(const Container&, Functor) [with Container = std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, Functor = void (*)(const std::string&)]':
main.cpp|116| instantiated from here
main.cpp|96| warning: unused variable 'it'

Program output:

v1
one
two
three
v2

My questions:

  • Why ForEach_v2doesn't it print anything?
  • Why does the compiler print an "unused variable" -warning for ForEach_v2?
+3
source share
3 answers

Do you want to

  inFunctor(*it);

not

  Functor(*it);
+8
source
template<class Container, class Functor>
void ForEach_v2(const Container & inContainer, Functor inFunctor)
{
    typename Container::const_iterator it = inContainer.begin(), end = inContainer.end();
    for (; it != end; ++it)
    {
        Functor(*it);
    }
}

It should be

template<class Container, class Functor>
void ForEach_v2(const Container & inContainer, Functor inFunctor)
{
    typename Container::const_iterator it = inContainer.begin(), end = inContainer.end();
    for (; it != end; ++it)
    {
        inFunctor(*it);
    }
}
+3
source

Here is your problem:

for (; it != end; ++it)
    {
        Functor(*it);
    }

Functoris now a type of function you passed in.

You need to write the following:

for (; it != end; ++it)
    {
        inFunctor(*it); //note this change!
    }

Now it will work!

+2
source

Source: https://habr.com/ru/post/1779466/


All Articles