0

This obvious question might be asked somewhere which i couldn't found, the nearest answer is this . I come from a C background and if you want to pass a function as argument in C You ought to use a pointer to function . but this :


void    increment ( int & n ) { n += 1; }

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

int main( void ) {
    int arr[] = {1, 2, 3, 4, 5};
    iterator(arr, 5, increment);
    return 0;
}

One answer (see link above) state that templated function can only accept either a type or a value !! Well function are not types, so what's the matter with typename F , the other possible option is that the function actually evaluate and return it's value to templated function parameter which definitely doesn't make sense, so my question. How exactly are functions can be passed as arguments to templated functions? what's going on behind the scenes ?

interesting
  • 149
  • 1
  • 10
  • 1
    Functions are not types, but functions have types, and that's the template parameter? – Sam Varshavchik Jul 01 '22 at 12:54
  • what does that mean exactly are we passing the types of return or/and parameters of the function, i didn't get it , can you clarify exactly what do you mean ?? – interesting Jul 01 '22 at 12:56
  • 1
    Templates are not functions. They are unicorns. They do not exist. Only when a template gets referenced they magically exist. In the case of a template for a function, the parameters to the function are used to deduce the type of its template parameters. In the example above, the type of the first "parameter", "arr" is `int []` which decays to `int *`, and that becomes the `T` parameter. Guess what? Exactly the same thing happens with the third parameter. It's a function pointer. Guess what its type is? It's `void (*)(int &)`. Guess what's the type of the `F` template parameter becomes? – Sam Varshavchik Jul 01 '22 at 13:02
  • my conclusion from your comment is 1) Function templates can accepts not just types or values ? but pointers to those types ? 2) The way it works behind the scenes is the compiler during the instantiation of the function template deduces what's the types that actually passed to the function . First is my conclusion correct ??? and second I know that's beyond my question but could you elaborate in how the compiler find out what's the actual type of the arguments are ? – interesting Jul 01 '22 at 13:13
  • 1
    It is true that template parameters can be types or values, but this is completely irrelevant for your template. Both of its parameters are types. That's what `typename` means, in the template declaration. Your second point is correct. It is the core fundamental principle in both C and C++ is that the types of all objects and expressions are known at compile time, and this has nothing to do with templates. The compiler knows what the actual types are because without knowing it the code cannot be compiled. – Sam Varshavchik Jul 01 '22 at 13:18
  • 1
    template parameter F can by anything in your code it is not constrained by a concept. Your code will only compile when F and T magically match up. To have succesful compilation F must either be a function pointer (with correct signature), a std::function or a lambda function (with correct signature)> (or some other functor). Your code by the way is still a shows a bit of "C" , (passing arrays by seperate size and pointer: can be avoided by using std::array/std:vector). And main doesn't need a void argument. – Pepijn Kramer Jul 01 '22 at 13:24
  • 1
    Function templates can accept both values and types `template` is also allowed. I don't really get what you mean with templates and pointers. Maybe reading a few sections here will help you understand : https://www.learncpp.com/cpp-tutorial/function-templates/ – Pepijn Kramer Jul 01 '22 at 13:27

1 Answers1

0

Functions have a type. There is nothing fundamentally different from passing increment to the function template compared to passing arr. Their types get deduced and then replaced as the template arguments.

Perhaps it get clearer without argument deduction:

iterator<int, void()(int&)>(arr, 5, increment);

or letting decltype deduce the type:

iterator<int, decltype(increment)>(arr,5,increment);

If iterator wasnt a template it would look something like this (for this particular call):

using F = void(*)(int&);
void iterator(int* arr, size_t size, F f);
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185