I am trying to execute the following code in C++. The program converts a lambda with no capture to a function pointer.
#include <utility>
template <typename R, typename... Args>
R run(R (*func)(Args...), Args&&... args) {
func(std::forward<Args>(args)...);
}
int main() {
run([] (int x, int y) {
return x + y;
}, 100, 200);
return 0;
}
However, when I compile it, I get the following error -
test.cc: In function ‘int main()’:
test.cc:11:20: error: no matching function for call to ‘run(main()::<lambda(int, int)>, int, int)’
}, 100, 200);
^
test.cc:11:20: note: candidate is:
test.cc:4:3: note: template<class R, class ... Args> R run(R (*)(Args ...), Args&& ...)
R run(R (*func)(Args...), Args&&... args) {
^
test.cc:4:3: note: template argument deduction/substitution failed:
test.cc:11:20: note: mismatched types ‘R (*)(Args ...)’ and ‘main()::<lambda(int, int)>’
}, 100, 200);
^
As far as I am aware this is fine. I have also tried explicitly giving the template arguments in the call to run. That doesnt work either.
Any ideas?
A lambda is not a function pointer. It cannot be deduced as a function pointer. It is a closure. However, if (and only if) it takes no capture, it can be explicitly converted to a function pointer via some sorcery:
run(+[] (int x, int y) {
// ^^^
return x + y;
}, 100, 200);
That said, it'd be better to simply have run take an arbitrary callable:
template <typename F, typename... Args>
auto run(F func, Args&&... args)
-> decltype(func(std::forward<Args>(args)...)) // only for C++11
{
return func(std::forward<Args>(args)...);
}
Related
Check the below code.
#include <future>
template <class F, class... Args>
void do_something(F f, Args... args) {
using return_type = typename std::result_of<F(Args...)>::type;
// Why below gives an error?
std::packaged_task<return_type(Args...)> task(f, args...);
}
int func(int a, int b) {
}
int main() {
do_something(func, 1, 2);
}
The packaged_task constructor gives a following error.
error: no matching function for call to 'std::packaged_task<int(int, int)>::packaged_task(int (*&)(int, int), int&, int&)'
8 | std::packaged_task<return_type(Args...)> task(f, args...);
The thing I don't understand is that why f and args became a reference type in the constructor? The Args... were int, int types whereas args... just became int&, int&. Where is this coming from?
packaged_task do not have the signature you want.
compiler is saying there is no such function. (probably with candidates below it)
I have written a generic exponential backoff retry loop in C++11. I'm using std::function to pass the callable to retry loop. callable will be retried if isRetriable function returns true.
#include <algorithm>
#include <cassert>
#include <chrono>
#include <functional>
#include <iostream>
#include <thread>
constexpr int64_t max_backoff_milliseconds = 30000; // 30 seconds
template <class R, class... Args>
R Retry(int max_retry_count, int64_t initial_dealy_milliseconds,
const std::function<bool(R)> &isRetriable,
const std::function<R(Args...)> &callable, Args &&... args)
{
int retry_count = 0;
while (true) {
auto status = callable(std::forward<Args>(args)...);
if (!IsRetriable(status)) {
return status;
}
if (retry_count >= max_retry_count) {
// Return status and abort retry
return status;
}
int64_t delay_milliseconds = 0;
if (initial_dealy_milliseconds > 0) {
delay_milliseconds =
std::min(initial_dealy_milliseconds << retry_count,
max_backoff_milliseconds);
}
std::cout << "Callable execution failed. Retry Count:"
<< retry_count + 1 << std::endl;
std::this_thread::sleep_for(
std::chrono::milliseconds(delay_milliseconds));
retry_count++;
}
}
bool isRetriable(int status) {
if (status == 5)
return true;
return false;
}
int foo(int x, int y) {
static int a = 1;
a += (x + y);
return a / 6;
}
int main() {
auto result = Retry(1000, 100, isRetriable, foo, 1, 3);
std::cout << result << std::endl;
return 0;
}
When I compile it, I'm getting below error:
prog.cpp: In function ‘int main()’:
prog.cpp:50:71: error: no matching function for call to ‘Retry(int,
int, bool (&)(int), int (&)(int, int), int, int)’
auto result = Retry<int, int, int>(1000, 100, isRetriable, foo, 1, 3);
^
prog.cpp:11:3: note: candidate: template<class R, class ... Args> R
Retry(int, int64_t, const std::function<bool(R)>&, const
std::function<_Res(_ArgTypes ...)>&, Args&& ...)
R Retry(int max_retry_count,
^~~~~
prog.cpp:11:3: note: template argument deduction/substitution failed:
prog.cpp:50:71: note: mismatched types ‘const
std::function<int(_ArgTypes ...)>’ and ‘int(int, int)’
auto result = Retry<int, int, int>(1000, 100, isRetriable, foo, 1, 3);
^
Could someone explain to me why I have this error?
I'm sure there's a good duplicate for this but...
Here's a shorter reproduction:
template <typename T> void foo(std::function<bool(T)> ) { }
bool maybe(int ) { return false; }
foo(maybe); // error: no matching function call to 'foo(bool (&)(int))'
You may ask - what?! maybe is something that's callable with some T that returns bool. But that's not how template deduction works. In order to deduce std::function<bool(T)> against an argument, that argument needs to be a std::function. maybe isn't a std::function, it's just a function, so that deduction fails. Any kind of deduction with a different kind of expression will also fail:
foo([](int ) { return true; }); // also error
Basically, trying to deduce a std::function is almost always the wrong thing to do. First, it's wrong because it won't work. Second, it's wrong because even if it did work, you're incurring type erasure in a context in which you probably don't need it.
What you want to do instead is deduce arbitrary callables, and then determine what these other arguments are based on those callables. The return type of callable is just what you get when you call callable with Args..., and you want to ensure that isRetriable is a predicate on that type.
One approach to that is:
template <typename Predicate, typename Callable, typename... Args,
// figure out what the callable returns
typename R = std::decay_t<std::invoke_result_t<Callable&, Args...>>,
// require that Predicate is actually a Predicate
std::enable_if_t<
std::is_convertible_v<std::invoke_result_t<Predicate&, R>, bool>,
int> = 0>
R Retry(int max_retry_count, int64_t initial_dealy_milliseconds,
Predicate&& isRetriable,
Callable&& callable,
Args&&... args)
{
// ....
}
I would like to pass a template method as a template argument.
I don't understand why I am getting this error:
no known conversion for argument 1 from '<unresolved overloaded function type>' to 'void (B::*&&)(int&&, double&&)
Here is the code:
struct A {
template <class Fn, class... Args>
void f(Fn&& g, Args&&... args) {
g(std::forward<Args>(args)...);
}
};
struct B {
template <class... Args>
void doSomething(Args&&... args) {}
void run() {
A a;
a.f(&doSomething<int, double>, 1, 42.); // error here
}
};
int main() {
B b;
b.run();
return 0;
}
Any ideas?
The root cause for the error is that you need an object to call the member function. However, with current code, the error is not that straightforward.
Change calling site to
a.f(&B::doSomething<int, double>, 1, 42.)
And you will see much better error:
error: must use '.' or '->' to call pointer-to-member function in 'g
(...)', e.g. '(... ->* g) (...)'
doSomething is a member function, as such, it cannot be called without an object, which you are trying to do
g(std::forward<Args>(args)...);
^
where is the instance?
One solution to this is to wrap doSomething in a lambda:
a.f([](B& instance, int a, int b) { instance.doSomething(a, b); }, *this, 1, 42.);
If you can use C++17, you could also use std::invoke:
template <class Fn, class... Args>
void f(Fn&& g, Args&&... args) {
std::invoke(g, std::forward<Args>(args)...);
}
and then when calling f:
a.f(&B::doSomething<int, double>, this, 1, 42.);
I receive the following error when attempting to compile a lone C++ testing file under G++ with C++11 in place.
spike/cur_spike.cpp: In function ‘int main()’:
spike/cur_spike.cpp:60:44: error: no matching function for call to ‘callFunctionFromName(<unresolved overloaded function type>, std::__cxx11::string&)’
callFunctionFromName (outputLine, param);
^
spike/cur_spike.cpp:49:7: note: candidate: template<class funcT, class ... Args> funcT callFunctionFromName(funcT (*)(Args ...), Args ...)
funcT callFunctionFromName (funcT func(Args...), Args... args) {
^
spike/cur_spike.cpp:49:7: note: template argument deduction/substitution failed:
spike/cur_spike.cpp:60:44: note: couldn't deduce template parameter ‘funcT’
callFunctionFromName (outputLine, param);
^
Here's the code.
#include <iostream>
#include <string>
template <typename T>
void outputLine (T text) {
std::cout << text << std::endl;
}
template <typename funcT>
funcT callFunctionFromName (funcT func()) {
return func ();
}
template <typename funcT, typename... Args>
funcT callFunctionFromName (funcT func(Args...), Args... args) {
return func (args...);
}
int main () {
std::string param = "Testing...";
callFunctionFromName (outputLine, param);
return 0;
}
I'm currently building this on a Linux system using G++, this code snippet contains all code related to this issue. I'm particularly intrigued about the fact that the compiler is unable to deduce the template parameter funcT for some reason, even though the outputLine function has a clear return type of void.
Setting a pointer of outputLine using void (*outputLinePtr)(std::string) = outputLine and using the pointer as the argument instead does nothing. Any help would be much appreciated.
You can manually set template argument.
callFunctionFromName (outputLine<std::string>, param);
I think the snippet of code is self explanatory, but basically the template function ExecFunc should be able to execute another function and return its result. I know I can achieve similar results using decltype instead of result_of, but this question is to understand why what I've written does not work: the snippet does not compile on gcc v4.9.2.
This is what I have:
#include <type_traits>
int f(int i)
{
return i;
}
template<class F, class T>
auto ExecFunc(F f, T arg) -> typename std::result_of<F()>::type
{
return f(arg);
}
int main() {
auto a = ExecFunc(f, 3);
return 0;
}
and this is the compiler output:
prova.cpp: In function ‘int main()’:
prova.cpp:15:26: error: no matching function for call to ‘ExecFunc(int (&)(int), int)’
auto a = ExecFunc(f, 3);
^
prova.cpp:15:26: note: candidate is:
prova.cpp:9:6: note: template<class F, class T> typename std::result_of<F()>::type ExecFunc(F, T)
auto ExecFunc(F f, T arg) -> typename std::result_of<F()>::type
^
prova.cpp:9:6: note: template argument deduction/substitution failed:
prova.cpp: In substitution of ‘template<class F, class T> typename std::result_of<F()>::type ExecFunc(F, T) [with F = int (*)(int); T = int]’:
prova.cpp:15:26: required from here
prova.cpp:9:6: error: no type named ‘type’ in ‘class std::result_of<int (*())(int)>’
N.B.
this question might look like a duplicate of this one but the accepted solution doesn't work for me (at least, as far as I can tell I have incorporated the solution in my code).
The function you have is int f(int i) but you are calling F() which is unknown. std::result_of<F()>::type should be std::result_of<F(T)>::type.
Live Example
The problem is with the parameter of result_of, it should be:
-> typename std::result_of<F(T)>::type
This is the perfect time to use decltype
template<class F, class T>
auto ExecFunc(F f, T arg) -> decltype(f(arg))