Variable type of template lambda (C++) - c++

I'm implementing a lambda as variable.
In C++20 it works this way:
auto lambda = []<typename T>() -> const T& {
...
};
Now I want to store this kind of lambda function as a member variable of a struct:
struct A {
??? m_lambda;
A(??? lambda) : m_lambda(lambda) {}
};
Is there a way to do this?

You store any templated lambda the same ugly way you store ordinary ones:
constexpr auto lambda = []<typename T>() {};
struct Foo{
decltype(lambda) m_lambda;
Foo():m_lambda(lambda){}
};
This works because it is operator() that is actually templated, not the automatically-generated lambda type.
If you do not rely on inlining any calls to the lambda (for performance), you can store it in std::function<Ret(Args)> for correct signature.
std::function is also the only* option if the lambda cannot be defined before Foo as seems to be the case of your constructor.
struct A {
std::function<void()> m_lambda;
// Not a lambda per se.
A(std::function<void()> lambda) : m_lambda(std::move(lambda)) {}
};
The above is not a lambda exactly because it doesn't really make sense most of the time to take a lambda as parameter as each has a distinct type making the argument effectively redundant.
*One can always make A a class template and use CTAD for deduction, not sure you want to go that way though.

In c++20 you can do:
struct Foo
{
decltype([] <class T> () {/* ... */ }) m_lambda {};
};
That being said it doesn't make any sense to store a lambda as a data member. Lambdas cannot change so a method is the simple, preferred alternative.

Since your lambda is templated, you will need to contain the lambda directly in your object.
Fortunately, it's quite easy to do in C++20 (and C++17):
auto lambda = []<typename T>() -> const T& {
// ...
};
template<typename L> // <-- L is the lambda type
struct A {
L m_lambda;
A(L lambda) : m_lambda(lambda) {}
void foo() {
// Can call using many types using the template
int const& a = m_lambda.template operator()<int>();
float const& b = m_lambda.template operator()<float>();
}
};
int main() {
auto my_a = A{lambda}; // construct using the lambda and CTAD
my_a.foo();
}
If on the contrary you need A to only call one version of the template, you can wrap the lambda in another lambda:
struct A {
std::function<int const&()> m_lambda;
A(auto const& lambda) : m_lambda{
[lambda]{ return lambda.template operator()<int>(); }
} {}
void foo() {
// Can call and get a int const reference back
int const& a = m_lambda();
}
};

Related

Function pointer overloading using typedef

As I understand, typedef cannot be used for overloading but what if I need to use some different types as arguments to the function pointer?
How can I make it work with the following functionality?
{
public:
typedef void (*InitFunc)(float x);
typedef void (*InitFunc)(int a, char b); //Needs to be added
virtual void initialize(InitFunc init) = 0;
};
Edit:
I cannot use C++17, so can't use variant
As commented, the easiest way is a union, although not very type safe and C++-y. Here is an example with inheritance, since you commented that you want inheritance.
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
union InitFn {
FloatInit fi;
IntCharInit ici;
};
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
f.fi(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
As mentioned by other commenters, you can use std::variant to enhance type safety and get rid of the manual union definition:
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
typedef std::variant<FloatInit, IntCharInit> InitFn;
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
std::get<FloatInit>(f)(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
One solution is to create a simple wrapper class template instead, to allow the compiler to automatically generate instantiations as necessary. This is relatively simple if init is always guaranteed to be a non-member function (and by extension, an actual function and not a functor/lambda).
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> {
public:
// Supply component types if needed.
// Tuple used for params, for convenience.
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
// Create from pointer or reference.
constexpr InitFunc(func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator func_ptr_type() { return ptr; }
operator func_ref_type() { return *ptr; }
private:
// Actual function pointer.
func_ptr_type ptr;
};
// And a nice, clean creator, which can be renamed as necessary.
template<typename Init>
constexpr auto make(Init func) { return InitFunc<Init>(func); }
This creates a nice little wrapper that can easily be optimised out entirely, and will compile as long as C++14 support is available.
Note that you require a C++11 compiler (or variadic templates, rvalue references, perfect forwarding, and constexpr support) at the absolute minimum, and will need to modify make() to have a trailing return type for pre-C++14 compilers. I believe this is compatible with C++11 constexpr, but I'm not 100% sure.
If you want InitFunc to be able to accept pointers/references-to-member-function (including functors and lambdas), you'll need to provide an additional version to isolate it into a non-member "function", and likely bind it to a class instance. It may be worth looking into std::bind() in this case, although I'm not sure if it has any overhead.
In this case, I would suggest splitting the member types off into a base class, to reduce the amount of code you'll need to duplicate.
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
// Supply component types if needed.
// Tuple used for params, for convenience.
// Using actual function type as a base, similar to std::function.
template<typename Ret, typename... Params>
class InitFunc<Ret(Params...)> {
public:
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
};
// Non-member functions.
// As member types are now dependent types, we qualify them and use `typename`.
// Yes, it looks just as silly as you think it does.
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> : public InitFunc<Ret(Params...)> {
// Actual function pointer.
typename InitFunc::func_ptr_type ptr;
public:
// Create from pointer or reference.
constexpr InitFunc(typename InitFunc::func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(typename InitFunc::func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr typename InitFunc::return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator typename InitFunc::func_ptr_type() { return ptr; }
operator typename InitFunc::func_ref_type() { return *ptr; }
};
// See ecatmur's http://stackoverflow.com/a/13359520/5386374 for how to accomodate member functions.
// ...
// Non-member function make() is unaffected.
// An overload will likely be needed for member functions.
template<typename Init>
auto make(Init func) { return InitFunc<Init>(func); }
Despite the awkwardness inside our derived specialisation, any code that relies on InitFunc shouldn't (to my knowledge) see any changes to its API; the previous example will work just fine if we swap to this new InitFunc, and be none the wiser after recompilation.
Note that it will change the ABI, though, and thus any code compiled for the simpler InitFunc will need to be recompiled for this version.

std::vector of movable-only lambdas, is it possible?

I'd like to have a collection of lambdas, with the requirement that the lambas must not be copied, only moved.
This is because the lambas may need to move-capture some of their arguments that are not copy-constructible.
Example:
NonCopyableType varName ;
auto func = [a=move(varName)](){ ... } ; //varName is move-captured
After this I want to store func in a vector, but I can't use the std::function type because it requires the lambdas to be copyable.
vector<function<void()>> list ;
list.push_back(func) ; //won't work
Is it possible to do this some other way?
Sure. Just write your own function clone that is move-only. Here's a simplified version that only supports nullary callables, but you can see how it can be extended:
class move_function
{
struct placeholder {
virtual ~placeholder() = default;
virtual void call() = 0;
};
template <class T>
struct holder : placeholder {
T f;
void call() override { f(); }
};
std::unique_ptr<placeholder> f_;
public:
template <class F,
class R = std::result_of_t<F&()>,
std::enable_if_t<!std::convertible<std::decay_t<F>*, move_function*>::value, int> = 0>
move_function(F&& f)
: f_(new std::decay_t<F>{std::forward<F>(f)})
{ }
void operator()() const { f_->call(); }
};
All the implicitly defined special member functions already do the right thing for us.

Forward a function into a lambda-expression in c++11

For a Packaged_Task implementation in C++11
i want to achieve what i've expressed in C++14 Code below. In other words i want to forward into a lambda expression.
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = [f = std::forward<F>(f)]() mutable { return std::move(f); };
///...
I'm aware of workarounds for moving into a lambda (but unfortenately this workarounds need a default constructible Object, in my case the object is most often a lambda expression without default-constructor)
How about creating a wrapper struct which does a move during copy construction:(. (I know that's bad, makes me remember of auto_ptr)
template <typename F>
struct Wrapped {
using Ftype = typename std::remove_reference<F>::type;
Wrapped(Ftype&& f): f_(std::move(f)) {}
Wrapped(const Wrapped& o): f_(std::move(o.f_)) {}
mutable Ftype f_;
};
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
Wrapped<std::remove_reference<decltype(f)>::type> wrap(std::forward<F>(f));
auto f_holder = [wrap]() mutable { return std::move(wrap.f_); };
This is just a rough idea. Not compiled or tested.
NOTE: I have seen this technique before, do not remember whether it was on SO itself or on some blog.
First, let's boil down the question to its core: the function object is somewhat of a distraction. Essentially, you want to be able to create a lambda with a capture holding a move-only object. In C++11 that isn't directly supported which gave raise to the C++14 approach of allowing specification of how the capture is build.
For C++11 it is necessary to use a copy. Since the underlying type doesn't support copying, it become necessary to actually move the object instead of copying it. Doing so can be achieved by a suitable wrapper defining a copy constructor not really copying but rather moving. Here is an example showing that:
#include <utility>
struct foo {
foo(int) {}
foo(foo&&) = default;
foo(foo const&) = delete;
};
template <typename T>
class move_copy
{
T object;
public:
move_copy(T&& object): object(std::move(object)) {}
move_copy(move_copy& other): object(std::move(other.object)) {}
T extract() { return std::forward<T>(this->object); }
};
template <typename T>
void package(T&& object)
{
move_copy<T> mc(std::forward<T>(object));
foo g = [mc]() mutable { return mc.extract(); }();
}
int main()
{
foo f(0);
package(std::move(f));
}
The move_copy<T> wrapper actually just captures the argument the way it is passed: if an lvalue is being passed in, an lvalue is captured. To properly get hold of the contained object, the extract() member std::forward<T>()s the object: the function can be called only once safely as an object is potentially moved from there.
Breaking copy semantics by making it a move is a bad idea. If it was the only option, go for it, but it is not.
Instead, we can pass the moved value in as an argument to the lambda, and move it into the wrapping code.
curry_apply takes some value and a function object, and returns that function object with the value bound to the first argument.
template<class T, class F>
struct curry_apply_t {
T t;
F f;
template<class...Args>
auto operator()(Args&&...args)
-> typename std::result_of_t<F&(T&, Args...)>::type
{
return f(t, std::forward<Args>(args)...);
}
};
template<class T, class F>
curry_apply_t<typename std::decay<T>::type, typename std::decay<F>::type>
curry_apply( T&& t, F&& f ) {
return {std::forward<T>(t), std::forward<F>(f)};
}
Use:
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = curry_apply(
std::move(_future),
[](Future<R>& f) mutable { return std::move(f); };
);
basically we store the moved-in data outside of the lambda in a manually written function object. We then pass it in as an lvalue argument at the front of the lambda's argument list.
Here is a more complex version of the same solution.

C++11 lambda function as callback and default value

I want to pass a lambda function to another function:
template<typename T>
void test2(T fn){
fn();
}
test2([]{cout<<"Hi"});
But I also want a default empty function in test2. So I do the next:
auto empty_lambda = []{};
template<typename T = decltype(empty_lambda)>
void test(T fn = empty_lambda){
fn();
}
test();
And all good, but I can't put
auto empty_lambda = []{};
inside the class, so I have to keep it in global scope.
Can I improve this somehow? Except option with void test2(){ test2([]{}); }
If it doesn't have to be a lambda, you could more portably use a plain-old static member function:
class foo {
static void do_nothing() {}
public:
template<typename T = decltype(do_nothing)>
void test(T fn = do_nothing){
fn();
}
};
but if you really want lambda syntax, you can take advantage of the implicit conversion to function pointer:
class foo {
public:
template<typename T = void(*)()>
void test(T fn = []{}){
fn();
}
};
RETRACTION: Original answer is non-portable, the standard does not specify that any lambda closure has a literal type so as to be usable in a constant expression.
Believe it or not, you can use auto to declare a static data member (per C++11 ยง[dcl.spec.auto]/4):
class foo {
static constexpr auto empty_lambda = []{};
public:
template<typename T = decltype(empty_lambda)>
void test(T fn = empty_lambda){
fn();
}
};
constexpr decltype(foo::empty_lambda) foo::empty_lambda;
The definition of the constexpr static data member is - to say the least - messy. (Live code at Coliru).
You can use std::function like following :
class X
{
static std::function<void()> f;
template<typename T = decltype(f)>
void test(T fn = f){
fn();
}
};
std::function<void()> X::f = []{};
See HERE

Setter of a lambda function?

Consider the following dumb example :
class MyClass
{
public:
template <class Function>
inline double f(double x, Function&& function)
{
return function(x);
}
};
With this class, I can call MyClass::f(x, function), with a lambda function to execute it on x, with (I hope) no overhead. My question is : what would be the equivalent with the function as a settable member of the MyClass ?
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
// What are the setter and the type of the protected member _function ?
};
Lambda functions (as well as some other types of "callable" functions) can be wrapped and stored using the std::function template class, found in the <functional> header. Its template parameter is a function signature with the syntax
ReturnType(ArgumentType1, ArgumentType2, ...)
so in your case the whole function wrapper type becomes
std::function<double(double)>
and thus, your code becomes
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
void setFunction(std::function<double(double)> && f)
{
_function = f;
}
private:
std::function<double(double)> _function;
};
std::function is "more" than a wrapper for function pointers. As you might know, lambda functions can capture part of the variable context, which needs to be stored somewhere. std::function does this for you transparently.
Note that std::function does not support overloaded signatures / templated call operators for functors. When assigning a functor with a call-operator signature like T operator()(T value) to a std::function<double(double)>, it can only be called with this signature. So there is no std::function<T(T)> (unless T is already known, such as a template parameter of your class).
An alternative which might be more efficient in some cases (you need to benchmark / profile it), is to make your whole class a template class with the function type parameter being the template parameter. Then you can store a function as a member:
template<typename Function>
class MyClass
{
public:
MyClass(Function && f) :
_function(f)
{}
inline double f(double x)
{
return _function(x);
}
private:
Function _function;
};
In order to create such an object, you need to specify the template parameter, like this:
auto myLambda = [](double x){ return x * 0.25; };
MyClass<decltype(myLambda)> myObject { myLambda };
To avoid this ugly syntactic overhead, add a "maker" function which takes advantage of template type deduction:
template<typename Function>
auto makeMyClass(Function && f) -> MyClass<Function> {
return MyClass<Function>(f);
}
Then, the code becomes more readable, with use of auto again:
auto myLambda = [](double x){ return x * 0.25; };
auto myObject = makeMyClass(myLambda);
You would have to use an std::function wrapper, possibly letting the constructor initialize it from an input callable object:
#include <functional> // <== REQUIRED FOR std::function
class MyClass
{
public:
template<typename F>
MyClass(F&& f) : _function(std::forward<F>(f)) { }
inline double f(double x)
{
return _function(x);
}
private:
std::function<double(double)> _function;
};
Notice, that this may bring you some run-time overhead, but the design is simple and flexible. Unless you can prove this run-time overhead is a bottleneck for your software's performance requirements, this run-time overhead should not be a concern.