Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make for_each work with templates?

I am new to c++ and am trying to understand how for_each works. So I wanted to see how it works with templates and tried this code but it gives out an error

When I tried to use the for each in the main it worked as it should have

template <class T>
void forEachTest(T a[])
{
    for (int x : a)
        cout << x << endl;
}
int main()
{
    int a[5] = { 10, 50, 30, 40, 20 };
    forEachTest(a);
    return 0;
}
like image 793
BlazeReaper Avatar asked Aug 23 '19 04:08

BlazeReaper


2 Answers

I am new to c++ and am trying to understand how for_each works

If you meant the range-based for-loop as for_each here, it just syntactic sugar for the iterator based loop, which works for any objects for which begin and end member functions defined.

auto&& __range = range_expression;                     // (until C++17)
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) 
{
    range_declaration = *__begin;
    loop_statement
}

The begin and end iterators for an array(e.g. int a[size]) can easily be found by a and a + size respectively, as iterators are generalizations of pointers. Therefore, whenever iterate through an array(in a range-based for-loop), the compiler should be knowing the size of the underlying array.

In your version, the passed array will be deduced to int*(no size information available) instead of the actual type int a[5].

There are few options, by which the passed array can be deduced to the actual type:

  • Option - 1: Provide a non - type parameter for size of the array, with the following syntax.
    template <typename T, std::size_t N>
    void forEachTest(T const (&a)[N])
    //               ^^^^^^^^^^^^^^^^
    {
     for (int x : a)
         std::cout << x << std::endl;
    }
    
  • Option - 2: pass it by const - reference, since the values are not being modified inside the function.
    template <typename T>
    void forEachTest(T const (&a))
    //              ^^^^^^^^^^^^
    {
     for (int x : a)
         std::cout << x << std::endl;
    }
    
  • Option - 3: forward the array perfectly with forwarding reference.
    template <typename T>
    void forEachTest(T&& a)
    //               ^^^^^^
    {
     for (int x : a)
         std::cout << x << std::endl;
    }
    
like image 108
JeJo Avatar answered Nov 20 '22 00:11

JeJo


When you use

template <class T>
void forEachTest(T a[]) 
{
    for (int x : a)
        cout << x << endl;
}

the size of the array is not known in the function. Hence, there is no way to iterate over the elements of a.

You need to use a slightly different function template.

template <class T, size_t N>
void forEachTest(T (&a)[N]) 
{
    for (int x : a)
        cout << x << endl;
}
like image 3
R Sahu Avatar answered Nov 19 '22 22:11

R Sahu