why can't I convert a lambda to a std::function here? - c++

I need a function that generates other functions. Why doesn't the following not let me convert a lambda to a std::function? I've done that before.
#include <iostream>
#include <functional>
std::function<int()> funcGen(int param) {
std::function<int()> myGeneratedFunc =
[param](int input) -> int {
return input+param;
};
return myGeneratedFunc;
}
int main() {
std::function<int()> myFunc = funcGen(3);
std::cout << "this should be 4=3+1: " << myFunc(1) << "\n";
return 0;
}
On ideone I get the following error:
error: conversion from ‘funcGen(int)::<lambda(int)>’ to non-scalar type ‘std::function<int()>’ requested

std::function<int()> accepts a function which takes in no arguments and returns an int. Your proposed lambda takes in an int and returns an int.
Consider std::function<int(int)> instead:
#include <iostream>
#include <functional>
std::function<int(int)> funcGen(int param) {
std::function<int(int)> myGeneratedFunc =
[param](int input) -> int {
return input+param;
};
return myGeneratedFunc;
}
int main() {
std::function<int(int)> myFunc = funcGen(3);
std::cout << "this should be 4=3+1: " << myFunc(1) << "\n";
return 0;
}

Related

How to move a unique_ptr from one set to another? (C++)

The code below is giving the error: Call to deleted constructor of 'std::unique_ptr<int>' 'unique_ptr' has been explicitly marked deleted here passing argument to parameter 'item' here.
Could someone please explain why this is? I would have thought everything would be fine because I'm using std::move in the call to foo.add.
#include <iostream>
#include <memory>
#include <set>
class Foo {
public:
void add(std::unique_ptr<int> item) {
set.emplace(std::move(item));
}
private:
std::set<std::unique_ptr<int>> set;
};
int main() {
Foo foo;
std::set<std::unique_ptr<int>> set;
set.emplace(std::make_unique<int>(1));
set.emplace(std::make_unique<int>(2));
set.emplace(std::make_unique<int>(3));
for (auto &item : set) {
foo.add(std::move(item)); // error on this line
}
return 0;
}
Use c++ 17 extract() function.
example
#include <set>
#include <memory>
#include <iostream>
int main() {
auto s = std::set<std::unique_ptr<int>>{};
s.insert(std::make_unique<int>(10));
std::cout << s.size() << "\n";
auto it = s.extract(s.begin());
// Pointer type here just for clarification
std::unique_ptr<int> new_ptr = std::move(it.value());
std::cout << s.size() << "\n";
std::cout << *new_ptr << "\n";
}
Then instead of your for each loop you might use a while loop:
while (!set.empty()) {
auto it = set.extract(set.begin());
foo.add(std::move(it.value());
}

c++ : target of instance of std::function returns null pointer

The following code compiled:
#include <iostream>
#include <functional>
typedef void (*f_type) (int a);
void say(int a)
{
std::cout << a << "!" << std::endl;
}
int main()
{
int a=5;
say(a);
std::function<void(int)> fn{say};
f_type fn_pointer = fn.target<void(int)>();
if(fn_pointer)
fn_pointer(a);
else
std::cout << "null ptr" << std::endl;
return 0;
}
but when executed prints:
5!
nullptr
I would like to understand why target returned an empty ptr, and not a pointer to the function "say".
note : it compiles for c++ up to c++14, for c++17 onward, compilation fails with error (which is cryptic to me):
In file included from /usr/include/c++/7/functional:58:0,
from main.cpp:11:
/usr/include/c++/7/bits/std_function.h: In instantiation of ‘_Functor* std::function<_Res(_ArgTypes ...)>::target() [with _Functor = void(int); _Res = void; _ArgTypes = {int}]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',28)">main.cpp:28:46</span>: required from here
/usr/include/c++/7/bits/std_function.h:733:9: error: invalid use of const_cast with type ‘void (*)(int)’, which is a pointer or reference to a function type
return const_cast<_Functor*>(__func);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reproduced it on VS2017, seems like the target method returns a pointer to pointer (as in returning a pointer to the actual function pointer stored in the object), and expecting its template type argument accordingly. Here is a modified example that works:
#include <iostream>
#include <functional>
typedef void(*f_type) (int a);
void say(int a)
{
std::cout << a << "!" << std::endl;
}
int main()
{
int a = 5;
say(a);
std::function<void(int)> fn{say};
f_type* fn_pointer = fn.target<void(*)(int)>();
if (fn_pointer)
(*fn_pointer)(a);
else
std::cout << "null ptr" << std::endl;
return 0;
}
Confirmed target returning a pointer to the actual function pointer by running the following:
#include <iostream>
#include <functional>
typedef void(*f_type) (int a);
void say(int a)
{
std::cout << a << "!" << std::endl;
}
void say_boo(int a)
{
std::cout << "booooo" << std::endl;
}
int main()
{
int a = 5;
std::function<void(int)> fn{say};
f_type* fn_pointer = fn.target<void(*)(int)>();
(*fn_pointer)(a);
fn = say_boo;
(*fn_pointer)(a);
return 0;
}
This produced the following output:
5!
booooo

Expand variadic arguments in initializer list fails

I try to create a simple program in which I want to create vector of future arguments.
I created a wrapper function which is used to submit lambda functions and stores internally in a vector the future objects
I use an intermediate step in which I create an initiliazer_list using variadic arguments . But fails to compile. I try to use to call a function in order to push the elements in the vector and fails to compile as well
Below is the code
#include <iostream>
#include <thread>
#include <future>
#include <functional>
#include <cstdlib>
#include <chrono>
#include <initializer_list>
using namespace std;
using FunctPtr = function<int(int, int) >;
using FutureInt = future<int>;
using AsyncVector = vector<FutureInt>;
AsyncVector asyncVec;
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
auto initList {pFunc... };
for (auto & element : initList)
{
asyncVec.emplace_back(async(launch::async, element,4,5));
}
}
int main()
{
int a;
int b;
auto addPtr = [](int x, int y)->int
{
std::cout << "add :" << x + y << std::endl;
return x + y;
};
auto multPtr = [](int x, int y)->int
{
std::cout << "mult :" << x * y << std::endl;
return x * y;
};
// submit(add,4,5);
submit(addPtr, multPtr);
for (auto & v : asyncVec)
{
std::cout << "Wait for " << v.get() << std::endl;
}
}
Yes, they are of different types so cannot be in the same init-list easily.
Your best options should probably be:
Either push them all into asyncVec in the same fold-expression.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
(asyncVec.emplace_back(async(launch::async, std::move(pFunc), 4, 5)), ...);
}
Or, if they all are of the same signature, type-erase them, like keeping them in an array of std::function.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
for (auto &&element: {std::function<int(int, int)>(std::move(pFunc))...})
{
asyncVec.emplace_back(async(launch::async, std::move(element), 4, 5));
}
}
(I have specified function signature explicitly though compiler should be able to deduce it.)
Or, if all closures are captureless and of the same signature, simply cast them to the same type when calling submit:
using SameType = int (*)(int, int);
submit(static_cast<SameType>(addPtr), static_cast<SameType>(mulPtr));
This way your original submit should work as is.

Propose to the user to rewrite functions with lambda

I'm doing tests to understand lambdas. I am trying to offer to the users the ability to rewrite a function directly in the main function. Let me explain:
#include <iostream>
using namespace std;
class A {
public:
virtual bool execute() {};
};
class B : public A {
public:
bool execute() { cout << "Execute in B" << endl; }
};
int main() {
B newB;
newB.execute();
newB.execute() { cout << "Execute in New B" << endl; } ;
newB.execute();
return 0;
}
This source code doesn't work because it's illegal to rewrite a function like that. What would be for you, the best way to rewrite a function like that in C ++ 14? With lambda? Without lambda?
I want do like in Javascript, overloading a function like that: newB.somefunction = function(...) { ... };. I want the function to be written in source code by a user of my Library. In a way a callback function.
my question is the following: How to write a callback function or Lambda expressions to rewrite a method outside a class/object?
Solution proposed by Exagon with variable :
#include <iostream>
#include <functional>
class B {
public:
int global=0;
std::function<void()> execute{
[](){
std::cout << "Hello World" << std::endl;
}
};
};
int main() {
B newB;
newB.execute();
newB.execute();
newB.execute = [newB](){std::cout << newB.global << " = FOOBAR\n";};
newB.execute();
return 0;
}
You can do this using std::function from the functional header.
Then make a std::function member and create a setter for this member.
the execute member function need to call this std::function member.
you can pass a lambda into the setter method.
here is my approach:
#include <iostream>
#include <functional>
class B {
public:
void execute() {_f();}
void setFunction(std::function<void()> f){ _f = f;}
private:
std::function<void()> _f{[](){std::cout << "Hello World" << std::endl;}};
};
int main() {
B newB;
newB.execute();
newB.execute();
newB.setFunction([](){std::cout << "FOOBAR\n";});
newB.execute();
return 0;
}
the output is:
Hello World
Hello World
FOOBAR
Since you are after something "JavaScript-like" you could do it like this:
#include <iostream>
#include <functional>
class B {
public:
std::function<void()> execute{
[](){
std::cout << "Hello World" << std::endl;
}
};
};
int main() {
B newB;
newB.execute();
newB.execute();
newB.execute = [](){std::cout << "FOOBAR\n";};
newB.execute();
return 0;
}
Which has the same output.
here is a live demo

Compare of std::function with lambda

How to compare of std::function with lambda?
#include <iostream>
#include <functional>
using namespace std;
int main()
{
using Type = void( float, int );
std::function<Type> a;
auto callback = []( float d, int r )
{
cout << d << " " << r << endl;
};
static_assert( std::is_same< Type , decltype( callback ) >::value, "Callbacks should be same!" );
a(15.7f, 15);
}
Because in case of first parametr of lambda would be int - code would compile with 1 warning. How to protect code?
The type of the callback is not a simple function. A lambda with no captures can decay to function pointer but it isn't a function pointer. It's an instance of a local class.
If you want to ensure a specific function type for a lambda, you can do that by forcing the decay to function pointer type:
#include <iostream>
#include <functional>
using namespace std;
int main()
{
using Type = void( float, int );
std::function<Type> a;
auto callback = []( float d, int r )
{
cout << d << " " << r << endl;
};
// Ensures desired type.
{
Type* const func_ptr = callback; (void) func_ptr;
}
a = callback;
a(15.7f, 15);
}