Considering the following toy example:
#include <iostream>
template <typename T>
void foo(T func, int *i) {
if (i) {
func(*i);
} else {
func();
}
}
int main() {
auto n = new int{2};
foo([](int x) { std::cout << x << std::endl; }, n);
foo([]() { std::cout << "Foo" << std::endl; }, nullptr);
return 0;
}
I want to create a function which receives lambdas functions with different signatures and call them inside its scope. If I do not call the lambda function inside foo, it compiles fine, but if I call it, the code does not compile.
Is there any way of receiving lambdas with different signatures and call it in a function?
Inside your function template, T has to be determined as one specific type, and remains that type throughout the entirety of that instantiation.
You can, however, accomplish what you want by making foo a variadic template, and passing the parameter pack through to the lambda that was passed in:
#include <iostream>
template <typename T, typename ...Args>
void foo(T func, Args... args) {
func(std::forward<Args>(args)...);
}
int main() {
auto n = new int{ 2 };
foo([](int x) { std::cout << x << std::endl; }, n[0]);
foo([]() { std::cout << "Foo" << std::endl; });
foo([](int a, int b) { std::cout << a + b << "\n"; }, 3, 2);
}
This way foo only needs to contain one invocation of func, which has a consistent type throughout each instantiation--but can vary from one instantiation to the next.
In this case, when the function you're passing doesn't take any arguments, you don't pass a special value for the argument. If it doesn't take an argument, you just don't pass an argument.
In the first case where you instantiate the template function with:
foo([](int x) { std::cout << x << std::endl; }, n);
The compiler creates the function where (T func) is a callable taking an int as function, therefore you can't do:
void foo(T func, int *i) {
if (i) {
func(*i);
}
//else
//{
// func(); // Can't call T func with no argument.
//} // Commenting this out will compile.
}
When you instantiate the template function with:
foo([]() { std::cout << "Foo" << std::endl; }, nullptr);
The compiler creates the function:
void foo(T func, int *i); // Where T func is a callable taking no arguments
So, in contrast to the previous example, you must must call T func with no arguments given. Therefore you can't do:
template <typename T>
void foo(T func, int *i)
{
//if (i) {
// func(*i); // Can't call T func with one argument, because
// T func function template has been instantiated
// as T func taking no arguments.
//}
//else
{
func(); // This obviously is fine.
}
}
Related
I want to default a lambda argument in a template function but it fails to compile. What am I missing?
template <typename F>
void foo(
F f = [](){
std::cout << "Hello!\n";
}
) {
f();
}
int main() {
foo(); // 1. does not compile
foo([](){ // 2. this is ok
std::cout << "Hello!\n";
});
}
You can't deduce the template parameter of a function from the default function arguments. See this question for details on why this restriction is in place.
So you must provide a default template parameter yourself. Since you need both the type and the value of the lambda, a simple way to do this would be to write the lambda once, and then use it inside the function template.
auto lambda = []()
{
std::cout << "Bye!\n";
};
template <typename F = decltype(lambda)> // default parameter
void foo(F f = lambda) // default value
{
f();
}
Here's a demo
So I have a function where, using C++17, I'm able to apply any method from any object:
#include <functional>
template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
std::invoke(method, object, args...);
}
What I ask: Is there a way to improve this to require less work for the caller of the function when the method is overloaded.
Example use with overloaded methods:
#include <iostream>
class Foo
{
int bottles;
public:
void Edit ()
{
bottles = 666;
}
void Edit (int number)
{
bottles = number;
}
void Talk () const
{
std::cout << bottles << " bottles of beer of the wall" << std::endl;
}
};
class Bar
{
Foo foo;
void TrickEdit (int number)
{
// Because Foo::Edit is overloaded, we need to do some work:
using Method = void (Foo::*)(int);
Method ptr = &Foo::Edit;
ApplyMethod(foo, ptr, number);
}
void TrickTalk () const
{
// it's a lot neater when the method isn't overloaded:
ApplyMethod(foo, &Foo::Talk);
}
public:
void Trick ()
{
TrickEdit(900);
TrickTalk();
}
};
int main ()
{
Bar().Trick();
return 0;
}
I'm trying to perform the work at the function instead. The problem seems to lie in that &Foo::Edit has two different locations, depending on which Edit we're referring to.
In C++ FAQ - Pointers to member functions by Stroustrup and other reputable authors, I read:
Question: I need something like function-pointers, but with more flexibility and/or thread-safety; is there another way?
Answer: Use a functionoid.
Question: What the heck is a functionoid, and why would I use one?
Answer: Functionoids are functions on steroids. Functionoids are strictly more powerful than functions, and that extra power solves some (not all) of the challenges typically faced when you use function-pointers. [...] Functionoids don’t solve every problem encountered when making flexible software, but they are strictly more powerful than function-pointers and they are worth at least evaluating. In fact you can easily prove that functionoids don’t lose any power over function-pointers, since you can imagine that the old-fashioned approach of function-pointers is equivalent to having a global(!) functionoid object. Since you can always make a global functionoid object, you haven’t lost any ground. QED.
Given that the "power" of programming is basically the reduction of work duplication, and that with a normal function we would avoid the extra work at the call site that I've outlined in my problem, the FAQ answer implies that there should be a solution to this using functionoids. However, for the life of me, I can't see how functionoids would help in this case.
Maybe you can use something like that:
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
void Do(int,int) { std::cout << "Do 2 parms" << std::endl; }
};
template < typename OBJ_TYPE, typename ... ARGS >
auto Invoke( OBJ_TYPE&& obj, void( std::remove_reference<OBJ_TYPE>::type::* func)(ARGS...), ARGS&& ... args )
{
return std::invoke( func, obj, args... );
}
int main()
{
A a;
Invoke( a, &A::Do);
Invoke( a, &A::Do, 1);
Invoke( a, &A::Do,1,2);
}
The idea is simply to fix the pointer type of the member function pointer to the given arguments in the parameter pack.
If someone has an idea how to automatically determine the return type, so that we also can use overloads with different return types, that would be very funny! I end up in a recursion :-)
If we simply specify the return type, we can use it as follows:
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
int Do(int,int) { std::cout << "Do 2 parms" << std::endl; return 42;}
};
template < typename RETURN_TYPE, typename OBJ_TYPE, typename ... ARGS >
auto Invoke( OBJ_TYPE&& obj, RETURN_TYPE( std::remove_reference<OBJ_TYPE>::type::* func)(ARGS...), ARGS&& ... args )
{
return std::invoke( func, obj, args... );
}
int main()
{
A a;
Invoke<void>( a, &A::Do);
Invoke<void>( a, &A::Do, 1);
int retval = Invoke<int>( a, &A::Do,1,2);
std::cout << retval << std::endl;
}
You can write a variable template that specifies what Args... should be.
template <typename... Args>
struct Overload {
template<typename R, typename O>
operator R(O::*)(Args...) (R(O::*p)(Args...)) const { return p; }
template<typename R, typename O>
operator R(O::*)(Args...) const (R(O::*p)(Args...) const) const { return p; }
};
template <typename... Args>
Overload overload;
Which is used like
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
void Do(int,int) { std::cout << "Do 2 parms" << std::endl; }
};
template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
std::invoke(method, object, args...);
}
int main()
{
A a;
ApplyMethod( a, overload<>(&A::Do));
ApplyMethod( a, overload<int>(&A::Do), 1);
ApplyMethod( a, overload<int, int>(&A::Do),1,2);
}
This is what Qt does for it's modern signals and slots.
I am creating a class that allows me to store lambdas that need to be executed (in order) at a point in the future.
class Promise{
private:
//snip//
std::vector<std::function<void()>> lchain;
public:
//snip//
void then(const std::function<void()> &f){
if (this->resolved) {//If the promise is resolved we just call the newly added function, else we add it to the lchain queue that will be processed later
f();
return;
}
lchain.push_back(f);
}
void launch(){
this->resolved = true;
for (auto &fun: this->lchain)
fun();
}
}
It is obvious that it will only work with lambdas with a signature like [&](){} but some of the tasks need to work with an arbitrary number of parameters of arbitrary types (both, parameters and types are known in advance, when the function is added to the queue).
An example driver program that currently works is
int main(){
Promise* p = new Promise([](){
std::cout << "first" << std::endl;
})->then([](){
std::cout << "second" << std::endl;
});
Promise->launch(); //In my code promise chains are picked up by worker threads that will launch them.
}
An example program I would like to execute:
int main(){
Promise* p = new Promise([](){
return 5;
})->then([](int n){
return n*n;
})->then([](int n){
std::cout << n << std::endl; //Expected output: 25
});
Promise->launch();
}
Things that I am struggling to do:
Storing lambdas of mixed signatures in a std::vector
Making the then() method call f with the arguments associated with f
Making the then() function return the result of f so it can be fed to the next lambda in the chain (preferably binding it before storing the lambda in the vector)
I have been searching in stackoverflow the whole day but the closest I got was this but I would like something that can be done in the then() method to simplify the program code as it would be a pain to bind every single lambda before calling the then() method.
I have something that I think does what you want. I'll start with an example and then introduce the implementation.
int main(){
Promise p([] {
return 5;
});
p.then([](int n) {
return n*n;
}).then([](int n) {
std::cout << n << '\n';
});
p.launch();
struct A { int n; };
struct B { int n; };
struct C { int n; };
Promise q([](A a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{2};
});
q.then([](B b) {
std::cout << "B " << b.n << '\n';
return C{3};
}).then([](C c) {
std::cout << "C " << c.n << '\n';
});
q.launch(A{1}, 111);
Promise<B(A, int)> r([](auto a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{5};
});
r.then([](auto b) {
std::cout << "B " << b.n << '\n';
return C{6};
}).then([](auto c) {
std::cout << "C " << c.n << '\n';
});
r.launch(A{4}, 222);
}
This outputs:
25
A 1 111
B 2
C 3
A 4 222
B 5
C 6
Some drawbacks:
Calling then after the promise has been resolved doesn't automatically call the function. Things get confusing in that situation and I'm not even sure if it's possible.
You can't call then multiple times on the same promise. You have to build a chain and call then on the result of the previous then.
If any of those drawbacks make this unusable, then you can stop reading this humongous answer.
The first thing we need is a way of getting the signature of a lambda. This is only used for the deduction guide so it isn't strictly necessary for the core concept to work.
template <typename Func>
struct signature : signature<decltype(&Func::operator())> {};
template <typename Func>
struct signature<Func *> : signature<Func> {};
template <typename Func>
struct signature<const Func> : signature<Func> {};
template <typename Ret, typename... Args>
struct signature<Ret(Args...)> {
using type = Ret(Args...);
};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...)> : signature<Ret(Args...)> {};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...) const> : signature<Ret(Args...)> {};
template <typename Func>
using signature_t = typename signature<Func>::type;
The next thing we need is a base class. We know the next promise must accept the return type of the current promise as an argument. So we know the argument type of the next promise. However, we don't know what the next promise will return until then is called so we need a polymorphic base to refer to the next promise.
template <typename... Args>
class PromiseBase {
public:
virtual ~PromiseBase() = default;
virtual void launch(Args...) = 0;
};
Now we have the Promise class itself. You can construct a promise with a function. As I alluded to above, a promise stores a pointer to the next promise in the chain. then constructs a promise from the given function and stores a pointer to it. There is only one next pointer so you can only call then once. There's an assertion to make sure this doesn't happen. launch calls the stored function and passes the result to the next promise in the chain (if there is one).
template <typename Func>
class Promise;
template <typename Ret, typename... Args>
class Promise<Ret(Args...)> : public PromiseBase<Args...> {
public:
template <typename Func>
explicit Promise(Func func)
: handler{func} {}
template <typename Func>
auto &then(Func func) {
assert(!next);
if constexpr (std::is_void_v<Ret>) {
using NextSig = std::invoke_result_t<Func>();
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
} else {
using NextSig = std::invoke_result_t<Func, Ret>(Ret);
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
}
}
void launch(Args... args) override {
if (next) {
if constexpr (std::is_void_v<Ret>) {
handler(args...);
next->launch();
} else {
next->launch(handler(args...));
}
} else {
handler(args...);
}
}
private:
using NextPromise = std::conditional_t<
std::is_void_v<Ret>,
PromiseBase<>,
PromiseBase<Ret>
>;
std::unique_ptr<NextPromise> next;
std::function<Ret(Args...)> handler;
};
Finally, we have a deduction guide.
template <typename Func>
Promise(Func) -> Promise<signature_t<Func>>;
Here's an online demo.
EDIT: Just to clarify "t" is successfully called when casted. The compiler knows and does state that it is a function pointer that takes an argument of type int. I supply a null int pointer to break the loop because it is calling itself recursively. It may just be a bug in the compiler.
I am trying to call a function from a template function argument.
I would assume that it would be possible to call the function without explicit casting but that does not seem to be the case. Using VC2013.
template<typename T>
void func(T t)
{
printf("calling func...\n");
if (t)
{
((void(__cdecl*)(int))t)((int)nullptr); // explicit casting is successful
t ((int)nullptr); // compile error: ``term does not evaluate to a function taking 1 arguments``
}
}
void main()
{
auto pe = func < int > ;
auto pf = func < void(__cdecl*)(int) >;
pf(pe);
}
You have the error for func<int> which becomes:
void func(int t)
{
printf("calling func...\n");
if (t)
{
((void(__cdecl*)(int))t)((int)nullptr); // bad casting
t ((int)nullptr); // compile error: int is not a callable object
}
}
When t is an int, of course you can't treat it like a function. You'll have to specialize the template for ints or use a different function. Also, please forget that there are C-style casts, they only serve to shoot yourself into the foot.
I don't understand what do you want exactly. But maybe something like this ?:
#include <iostream>
#include <type_traits>
template<typename T>
void call_helper(T value, std::true_type) // value is function
{
std::cout << "Function" << std::endl;
value(0);
}
template<typename T>
void call_helper(T value, std::false_type) // value is NOT function
{
std::cout << "Not function" << std::endl;
std::cout << value << std::endl;
}
template<typename T>
void call(T value)
{
call_helper(value, std::is_function<typename std::remove_pointer<T>::type>());
}
int main()
{
void (*f)(int) = call<int>;
call(f);
}
live example: http://rextester.com/DIYYZ43213
I'm trying to implement simple ScopedExit class. Here's the code:
#include <iostream>
#include <functional>
template<class R, class... Args>
class ScopedExit
{
public:
ScopedExit(std::function<R(Args...)> exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<R(Args...)> exitFunc_;
};
template<>
class ScopedExit<void>
{
public:
ScopedExit(std::function<void ()> exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<void ()> exitFunc_;
};
void foo()
{
std::cout << "foo() called\n";
}
class Bar
{
public:
void BarExitFunc(int x, int y)
{
std::cout << "BarExitFunc called with x =" << x << "y = " << y << "\n";
}
};
int main()
{
Bar b;
std::cout << "Register scoped exit func\n";
{
ScopedExit<void, int, int> exitGuardInner(std::bind(&Bar::BarExitFunc, &b, 18, 11));
}
ScopedExit exitGuardOutter(foo);
std::cout << "About to exit from the scope\n";
return 0;
}
So, there are a couple of questions:
How to pass exit's function arguments to it? For example, I bind BarExitFunc with two integer arguments: 18 and 11. So how can I pass it to the exitFunc_ in the destructor? I think I need something like invoke function with std::forward<>.
gcc 4.7.2 (from ideone.com) complains about exitGuardOutter. It says:
prog.cpp:60:16: error: missing template arguments before ‘exitGuardOutter’
prog.cpp:60:16: error: expected ‘;’ before ‘exitGuardOutter’
Thanks in advance.
How to pass exit's function arguments to it? For example, I bind BarExitFunc with two integer arguments: 18 and 11. So how can I pass it to the exitFunc_ in the destructor?
I can see no reason whatsoever to pass arguments to exitFunc_ at call time in the destructor. Whatever you do, you'll have to provide those arguments upfront in the ScopedExit constructor anyway.
The most straightforward way is simply to use a function<R()> and bind any required arguments at the definition site like you're already doing:
ScopedExit<R> guard(std::bind(someFunction, someArg, otherArg));
This allows you to get rid of the variadic template arguments altogether and simplifies your template a lot.
Now, if what is bothering you is that you have to type std::bind and you would rather use such a syntax:
ScopedExit<R> guard(someFunction, someArg, otherArg);
Really, I don't see the point since it makes the template more complicated, but why not... Just bind/forward the arguments in the constructor itself and still store a function<R()>:
template<typename... Args>
ScopedExit(std::function<R(Args...)> exitFunction, Args&&... args)
{
exitFunc_ = std::bind(exitFunction, std::forward<Args>(args)...);
}
Now you systematically bind the function even if there are no arguments to bind, so you may want to specialize your class to avoid this useless bind when there are no arguments. This is left as an exercise.
gcc 4.7.2 (from ideone.com) complains about exitGuardOutter
This is because foo isn't a std::function and the compiler can't deduce the correct template arguments. As already mentioned by #ForEveR you could just define your guard variable as ScopedExit<void> guard(foo);.
Or, wrapping it all up and keeping in mind what I first said (bind is best left out of your template and used at the definition site of your guard) you could just get rid of std::function in the constructor and generalize for any functor (which, BTW, is how the Standard library does whenever it needs a functor/callback). For storage you can just use std::function<void()> since it accepts non-void return types too:
class ScopedExit
{
public:
template<typename Functor>
ScopedExit(Functor exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<void()> exitFunc_;
};
int foo() { return 0; }
struct Bar {
void bye(int, int) {}
};
struct Baz {
void operator ()() {}
};
int main() {
const std::string what = "lambda!";
ScopedExit guard1([&]() { std::cout << "yay a " << what << std::endl; });
ScopedExit guard2(foo); // note how std::function<void()> accepts non-void return types
Bar b;
ScopedExit guard3(std::bind(&Bar::bye, &b, 1, 2));
ScopedExit guard4(Baz());
}
Note how your original variadic template class has now become a flexible non-template class with just a templated constructor whose template argument is deduced automatically, and which accepts almost[see note below] any kind of functor you can think about.
Note: I said almost any functor because this doesn't work with default arguments:
void foobar(int = 0) {}
ScopedExit guard5(foobar); // error: too few arguments to function
Even if you stored a Functor directly instead of a std::function<void()> you wouldn't be able to make use of the default arguments anyway (the signature of foobar is still void(int) even with a default argument) so one always has to handle this corner-case at the definition site with something like:
void foobar(int = 0) {}
ScopedExit guard5([]() { foobar(); });
1) You can save arguments in tuple for example. However, in your case, you can simply call exitFunc_() and function definition should be std::function<R()> exitFunction since you already bind arguments to function. Something like this probably
#include <iostream>
#include <functional>
#include <tuple>
template<size_t...>
struct indices {};
template<size_t N, size_t... Is>
struct gen_indices : gen_indices<N - 1, N - 1, Is...>
{
};
template<size_t... Is>
struct gen_indices<0, Is...> : indices<Is...>
{
};
template<class R, class... Args>
class ScopedExit
{
public:
ScopedExit(std::function<R(Args...)> exitFunction, Args&&... args)
: arguments_(std::forward_as_tuple(args...))
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
call(gen_indices<sizeof...(Args)>());
}
private:
template<size_t... Idx>
void call(indices<Idx...>)
{
exitFunc_(std::forward<Args>(std::get<Idx>(arguments_))...);
}
std::tuple<Args...> arguments_;
std::function<R(Args...)> exitFunc_;
};
template<>
class ScopedExit<void>
{
public:
ScopedExit(std::function<void ()> exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<void ()> exitFunc_;
};
void foo()
{
std::cout << "foo() called\n";
}
class Bar
{
public:
void BarExitFunc(int x, int y)
{
std::cout << "BarExitFunc called with x =" << x << "y = " << y << "\n";
}
};
int main()
{
Bar b;
std::cout << "Register scoped exit func\n";
{
ScopedExit<void, int, int> exitGuardInner
(
std::bind(&Bar::BarExitFunc, &b, std::placeholders::_1,
std::placeholders::_2), 10, 18
);
}
ScopedExit<void> exitGuardOutter(foo);
std::cout << "About to exit from the scope\n";
return 0;
}
2) Should be created like ScopedExit<void>.