0

Following on from a previous question, I was pointed to an answer. The answer however involved a lambda function and I am trying to pass a normal function through.

Using the below code as an example:

#include <iostream>
#include <functional>

void forloop(std::function<void()> func, int arg) {
    func(arg);
}


void print(int number) {
    std::cout << number << std::endl;
}


int main() {
    int n = 5;
    forloop(print, n);
}

The following error is returned in CLion.

/home/dave/JetBrains/CLion/bin/cmake/bin/cmake --build /home/dave/CLionProjects/csv/cmake-build-debug --target csv -- -j 2
Scanning dependencies of target csv
[ 50%] Building CXX object CMakeFiles/csv.dir/main.cpp.o
/home/dave/CLionProjects/csv/main.cpp: In function ‘void forloop(std::function<void()>, int)’:
/home/dave/CLionProjects/csv/main.cpp:5:13: error: no match for call to ‘(std::function<void()>) (int&)’
     func(arg);
             ^
In file included from /home/dave/CLionProjects/csv/main.cpp:2:0:
/usr/include/c++/6/functional:2122:5: note: candidate: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = void; _ArgTypes = {}]
     function<_Res(_ArgTypes...)>::
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/functional:2122:5: note:   candidate expects 0 arguments, 1 provided
/home/dave/CLionProjects/csv/main.cpp: In function ‘int main()’:
/home/dave/CLionProjects/csv/main.cpp:16:21: error: could not convert ‘print’ from ‘void (*)(int)’ to ‘std::function<void()>’
     forloop(print, n);
                     ^
CMakeFiles/csv.dir/build.make:62: recipe for target 'CMakeFiles/csv.dir/main.cpp.o' failed
make[3]: *** [CMakeFiles/csv.dir/main.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/csv.dir/all' failed
make[2]: *** [CMakeFiles/csv.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/csv.dir/rule' failed
make[1]: *** [CMakeFiles/csv.dir/rule] Error 2
Makefile:118: recipe for target 'csv' failed
make: *** [csv] Error 2

Apologies if this questions seems silly - I am a C++ noob.

Greg
  • 8,175
  • 16
  • 72
  • 125
  • 1
    You declared your `func` to take no arguments. – melpomene Sep 17 '17 at 14:43
  • `void()` is the signature of a function that accepts nothing, and returns nothing. What is the signature of `print`? Also, don't try to learn C++ by trial and error. It will only be a disservice to yourself. I strongly urge you to have a look at the [suggested reading material](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – StoryTeller - Unslander Monica Sep 17 '17 at 14:44
  • @StoryTeller Thank you for answering both my questions. I have been learning C++ for about a month now (both watching a [fantastic youtube series](https://www.youtube.com/watch?v=18c3MTX0PK0&list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb) as well as getting tutoring). Probably trying to learn quicker than my abilities allow - it's a rather frustrating not being able to implement techniques acquired in other languages. – Greg Sep 17 '17 at 14:49
  • 2
    @Dave - I really can't comment on the quality of the video tutorial, but bear in mind that any such tutorial is not peer reviewed. The books in the link I gave you *are* suggested by the whole of the C++ community on SO. – StoryTeller - Unslander Monica Sep 17 '17 at 14:50

1 Answers1

1

std::function<void()> means "function that returns void and takes no arguments". You're trying to pass print instead, which is a "function that returns void and takes an int". The types are mismatched.

Change forloop to:

void forloop(std::function<void(int)> func, int arg) { /* ... */ }

Also, don't use std::function to pass lambdas unless you have a good reason to do so. I suggest reading my article on the subject: "passing functions to functions".

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416