0

I've been doing some exercises in C++ and stumbled upon one, it was about creating a simple a templated function iterator that takes an array of any type and another templated function to do some processing in each element in the array, i've completed the exerisce to look like the following:

template <typename T >
void    increment(T& t)  {
        t += 1;
}

template <typename T, typename F>
void    iterate(T *arr, size_t size, F f) {
        for (size_t i = 0; i < size; i++) f(arr[i]);
}

int main( void )  {

        int tab[]= {0,1,2,3,4};
        SomeClass tab2[5];
        iterate(tab, 5, increment<int>);
        iterate(tab2, 5, increment<SomeClass>);
        return (0);
}

Those 2 tests in the main function is those which i wrote my self, now the exercise too provide some tests to check the solution, and it's tests almost the same, it uses a simple print() templated function instead of increment()

    template <typename T >
    void    print(const T& t) {std::cout << t << " "; };

Now the problem here is it uses the following instantiation for templated function iterate():

    iterate(tab, 5, print);
    iterate(tab2, 5, print);

Now according to what my understanding you cannot pass a templated function as argument without instantiation because it's not a regular function, it should be instantiated otherwise the compiler wouldn't know what type to create for the actual function ?? and indeed when i compiled the exercise's tests i got a:

no matching function for call to 'iterate'

so my question is am i correct and this is just a mistake in the exercise or the tests are correct and i'm the one who's missing something ?

interesting
  • 149
  • 1
  • 10

2 Answers2

2

Yes, you are correct. A function template cannot be passed as a template argument because it does not have a type yet.

What you can pass is a functor, either custom one with overloaded operator() or just a lambda. Are you sure the wording does not talk about functors?

The following code works:

auto print = [](const auto& t) {std::cout << t << " "; };
iterate(tab, 5, print);
iterate(tab2, 5, print);

This is also the approach many STL algorithms took.

Quimby
  • 17,735
  • 4
  • 35
  • 55
  • 1
    No, not at all the exercise subject is about `general iterator functions` and the syntax is exactly the same as i posted , believe it was just an unintended typo – interesting Jul 02 '22 at 08:21
1

The task may be expecting you to use function pointers. In this the parameter type of print can be deduced in some scenarios. Note that if you want both modifying and non-modifying functions (=functions taking a reference to const) to work, you need to pecify the template parameter for templates with a signature that could match both, e.g. your increment template.

template <typename T >
void increment(T& t)
{
    t += 1;
}

template <typename T>
void iterate(T* arr, size_t size, void (*f)(const T&)) {
    for (size_t i = 0; i < size; i++) f(arr[i]);
}

template <typename T>
void    iterate(T* arr, size_t size, void(*f)(T&)) {
    for (size_t i = 0; i < size; i++) f(arr[i]);
}

template <typename T >
void    print(const T& t) { std::cout << t << " "; };


int main(void) {
    int tab[] = { 0,1,2,3,4 };
    iterate(tab, 5, increment<int>); // not possible to deduce the template parameter for increment here (both const int and int would be signatures matching an overload of iterate)
    iterate(tab, 5, print); // template parameter of print deduced as int
}
fabian
  • 80,457
  • 12
  • 86
  • 114