Debugging decommissioning a template

Why the following work does not work:

std::string fn(int i) { sleep(i); // number of seconds to sleep for std::cout << "Exiting after pausing " << i << " seconds\n"; return std::to_string(i+1); } template<typename T, typename U> int simult( std::function<T(U)> f, std::vector<U> args) { return 666; } int main() { std::vector<int> args { 6, 5, 7 }; int r = simult(fn, args); } 

The simultaneous function is obviously not complete: I'm just trying to collect something at this stage. The idea is that you provide a function and an argument list, and at the same time apply the arguments piecewise to f using thread calls.

At this point, I'm just trying to figure out a compilation problem.

 simult.cc: In function 'int main()': simult.cc:43:25: error: no matching function for call to 'simult(std::__cxx11::string (&)(int), std::vector<int>&)' int r = simult(fn, args); ^ simult.cc:23:5: note: candidate: template<class T, class U> int simult(std::function<T(U)>, std::vector<U>) int simult( std::function<T(U)> f, std::vector<U> args) ^~~~~~ simult.cc:23:5: note: template argument deduction/substitution failed: simult.cc:43:25: note: mismatched types 'std::function<T(U)>' and 'std::__cxx11::string (*)(int) {aka std::__cxx11::basic_string<char> (*)(int)}' int r = simult(fn, args); ^ 
+6
source share
3 answers

Template calculations do not cause implicit conversion. Although a function type (pointer) is convertible to std::function , this conversion is never part of a template replacement.

You will need to build std::function and pass it to simlut :

 int r = simult(std::function<std::string (int)>(fn), args); 
+1
source

This does not work because custom conversions are not taken into account when the template argument is output.

You can either help the compiler by explicitly providing the template arguments, and call simult as:

 int r = simult<std::string, int>(fn, args); 

Live demo

Or you can do it with decltype like this:

 std::string fn(int i) { return std::to_string(i + 1); } template<typename T, typename U> int simult_impl(std::function<T(U)> f, std::vector<U> const &args) { return 666; } template<typename F, typename U> int simult(F f, std::vector<U> const &args) { return simult_impl<decltype(f(args[0])), U>(f, args); } 

Live demo

Edit:

If you want to return std::vector<T> provided that your compiler supports C ++ 14, you can change it as follows:

 template<typename T, typename U> std::vector<T> simult_impl(std::function<T(U)> f, std::vector<U> const &args) { return std::vector<T>(10, T{"666"}); } template<typename F, typename U> auto simult(F f, std::vector<U> const &args) { return simult_impl<decltype(f(args[0])), U>(f, args); } 

Live demo

+1
source

Using the sentence from @SergeyA, I was able to find the working code, now as a complete example:

 #include <functional> #include <iostream> #include <string> #include <future> #include <thread> #include <vector> #include <unistd.h> // for sleep. Not needed generally // declare a function that does what you want std::string fn(int i) { sleep(i); // number of seconds to sleep for std::cout << "Exiting after pausing " << i << " seconds\n"; return std::to_string(i+1); } template<typename T, typename U> std::vector<T> simult(std::function<T(U)> func, std::vector<U> const &args) { std::vector<std::future<T>> fs; for(auto& a:args) fs.push_back(std::async(func, a)); std::vector<T> results; for(auto &f:fs) results.push_back(f.get()); return results; } int main() { std::vector<int> args { 6, 5, 7 }; std::vector<std::string> results = simult(std::function<std::string (int)>(fn), args); std::cout << "Results are:\n"; for(auto&r:results) std::cout << r << "\n"; //results are returned in correct order return 0; } 

Compile:

 g++ simult.cc -o simult -lpthread 

Run:

 time -p simult Exiting after pausing 5 seconds Exiting after pausing 6 seconds Exiting after pausing 7 seconds Results are: 7 6 8 real 7.00 user 0.00 sys 0.00 

I am still a little puzzled by why C ++ cannot determine the type of function itself, but I think what matters is that it works. It seems that the calling box is overly detailed for me.

Change In the simult() function, instances of std::string replaced by T

Edit : changed std::vector<U> args to std::vector<U> const &args

+1
source

All Articles