Template function to print C-style array using for_each () function and lambda function

Simple thing. But I spent the last hour and couldn't figure it out.

When I compile the following code:

#include <iostream>
#include <sort.h>
#define array_len(arr) ( sizeof(arr) / sizeof (*arr) )

using namespace std;

template<typename ITER>
void printIt_works(ITER b, ITER e) {
    for_each(b, e, [](int it) { cout << it; } ); // putting int explicitly would work
                                                 // but it not generic
}

template<typename ITER>
void printIt_doesnt_work(ITER b, ITER e) {
    for_each(b, e, [](ITER it) { cout << *it; } );
}

int main() {
    int a[] = {5, 2, 4, 6, 1, 3};

    printIt_doesnt_work(a, a+array_len(a)); // how to make this work in a generic way.

    //merge_sort(a, a+array_len(a));
    selection_sort(a, 6);
    insertion_sort_decending(a, 6);
    insertion_sort(a, 6);
    return 0;
}

      

Compilation error I am getting:

In file included from d:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/algorithm:63:0,
                 from D:\Workspaces\CodeBlocks\Test\main.cpp:4:
d:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_algo.h: In function '_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = int*, _Funct = printIt_doesnt_work(ITER, ITER) [with ITER = int*]::<lambda(int*)>]':
D:\Workspaces\CodeBlocks\Test\main.cpp:17:5:   instantiated from 'void printIt_doesnt_work(ITER, ITER) [with ITER = int*]'
D:\Workspaces\CodeBlocks\Test\main.cpp:23:42:   instantiated from here
d:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_algo.h:4185:2: error: invalid conversion from 'int' to 'int*'
d:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_algo.h:4185:2: error:   initializing argument 1 of 'printIt_doesnt_work(ITER, ITER) [with ITER = int*]::<lambda(int*)>'

      

d: \ mingw \ bin ../ lib / gcc / mingw32 / 4.5.2 / include / C ++ / bits / stl_algo.h: 4185 where it for_each

calls the function passed to it as the third parameter:__f(*__first);

I understand the problem, my lambda function is declared pending int*

, but the template instance for_each

is calling it using int

. I just don't know how to solve it with generic

.

I can of course get by by making the type explicit but not generic:

for_each(b, e, [](int it) { cout << it; } );

      

+3


source to share


2 answers


One option is to use a new keyword decltype

to define the type of what is repeated:

template<typename ITER>
void printIt_works(ITER b, ITER e) {
    for_each(b, e, [](decltype(*b) it) { cout << it; } );
}

      

This does a lambda whose argument type is the type of what is repeated, which is exactly what you want.

If you don't have decltype

one available in your compiler, you can use a more massive type iterator_traits

for this:



template<typename ITER>
void printIt_works(ITER b, ITER e) {
    for_each(b, e, [](typename std::iterator_traits<ITER>::reference it) { cout << it; } );
}

      

But this is really ugly.

Hope this helps!

+6


source


An alternative to using a lambda function is to use ostream_iterator

:



#include <iterator>
#include <algorithm>

template<typename Iterator>
void printIt(const Iterator& begin, const Iterator& end) {
  typedef typename std::iterator_traits<Iterator>::value_type value_type;
  std::copy(begin, end, std::ostream_iterator<value_type>(cout));
}

      

+5


source







All Articles