for example, I can do something like:
void foo(int i)
{
std::cout << "fo is called with: " << i << "\n";
}
int main()
{
std::function<void(int)> fo = std::bind(&foo, std::placeholders::_1);
fo(5);
}
and output
fo is called with: 5
now I'm curious about if I can make a std::function that receive a std::function as argument,so I think of some function like:
void foAndFo(function<void(int)> foo)
{
std::function<void(int)> fo = std::bind(&foo, std::placeholders::_1);
fo(5);
}
but this can even not been compiled.
now I changed to something may call function pointer.
using foType = void(*)(int);
void foAndFo(foType foo)
{
std::function<void(int)> fo = std::bind(&foo, std::placeholders::_1);
fo(5);
}
now it can be compiled.But now I cannot std::bind it like:
int main()
{
std::function<foType> fo2 = std::bind(&foAndFo,std::placeholders::_1); //error
}
is it possible to use std::function as argument of std::function?
This is possible. Just drop the & before foo here:
void foAndFo(function<void(int)> fo)
{
std::function<void(int)> fo = std::bind(/*&*/foo, std::placeholders::_1);
fo(5);
}
The difference is that if foo is a void(int), both foo and &foo can be inserted where a function is expected. On the other hand, if foo is a std::function then the two are quite different: foo can be passed for a const std::function&, but &foo is a std::function*, a pointer to an object of the type std::function. The latter is not Callable.
Minimal working example:
#include <iostream>
#include <functional>
void foo(int i)
{
std::cout << "fo is called with: " << i << "\n";
}
int main()
{
std::function<void(int)> fo = std::bind(foo, std::placeholders::_1); // or &foo, both work
std::function<void(int)> fo2 = std::bind(fo, std::placeholders::_1); // Error if &fo is used
fo2(5);
}
Related
https://stackoverflow.com/a/31860104
#include <iostream>
#include <string>
template<class T>
auto optionalToString(T* obj)
-> decltype( obj->toString() )
{
return obj->toString();
}
auto optionalToString(...) -> std::string
{
return "toString not defined";
}
struct TA
{
std::string toString() const
{
return "Hello";
}
};
struct TB
{
};
Question> Given the proposed solution optionalToString, how I can use it to detect that TA has toString while TB doesn't.
A solution using can_apply from this code:
template<class T>
using toString_result = decltype(std::declval<T>().toString());
template<class T>
constexpr auto has_toString = can_apply<toString_result, T>::value;
Used like this:
struct TA
{
std::string toString() const
{
return "Hello";
}
};
struct TB
{
};
int main()
{
std::cout << has_toString<TA> << '\n';
std::cout << has_toString<TB> << '\n';
return 0;
}
DEMO
The given solution allows you to always get a string from any object. If it has a toString() member function, this will be used, otherwise, a default string. Usage example, given the above:
TA a;
TB b;
std::cout << "a: " << optionalToString(&a) << '\n';
std::cout << "b: " << optionalToString(&b) << std::endl;
However, you will not get a boolean value whether a or b has a toString() method. If you want that, you need something like the solution proposed by O'Neil.
How to pass lambda as template parameter.
For example this code
template<void (*callback)()>
void function() {
callback();
}
int main() {
function<[]() -> void { std::cout << "Hello world\n"; }>();
}
fails with error "invalid template argument for 'function', expected compile-time constant expression".
What I'm doing wrong.
Edit
I want to implement something like this
template<typename T,
T (*deserializer)(buffer *data),
void (*serializer)(T item, buffer *data)>
class Type {
public:
T item;
Type(T item) : item(item) {
}
Type(buffer *data) {
deserialize(data);
}
void serialize(buffer *data) {
serializer(item, data);
}
void deserialize(buffer *data) {
deserializer(data);
}
};
typedef Type<int, [](buffer* data) -> int { return -1; }, [](int item, buffer* data) -> void {}> IntType
typedef Type<long, [](buffer* data) -> long { return -1; }, [](long item, buffer* data) -> void {}> LongType
Lambdas in C++14, including their conversion to function pointers, are not constexpr.
In C++17, this is going to change. There are no stable compilers with that feature implemented that I'm aware of (if you find one, can you mention it in the comments below?).
At that point
constexpr auto tmp = []() -> void { std::cout << "Hello world\n"; };
function<+tmp>();
will definitely work. I am uncertain if
function<+[]() -> void { std::cout << "Hello world\n"; }>()
would work; there are some rules about lambdas in unevaluated contexts and inside template argument lists that may be separate from the constexpr lambda problem and may apply here.
We can hack it in C++14.
Create a template class that stores a static copy of a lambda and exposes a static function with the same signature (f_ptr) that calls that static copy of a lambda.
Instantiate it once globally with your lambda.
Pass a pointer to the f_ptr to your template.
So:
template<class L> struct stateless; // todo
template<class L> stateless<L> make_stateless(L l){return std::move(l);}
auto foo = make_stateless( []() -> void { std::cout << "Hello world\n"; } );
function< &foo::f_ptr >();
this is almost certainly not what you want.
The kind of template in the example does not take a type as a parameter, but rather a value. This value needs to be determinable at runtime, in order to instantiate the template, and the value of a lambda is not a compile time constant, so this method just wont do. The common way of sending functors to a function is:
template<typename Func>
void foo(Func&& f)
{
f();
}
And since you want a class template (please put such information in the question, not the comments), here is an example using classes:
#include <utility>
template<typename Func>
class MyClass
{
public:
MyClass(Func&& f) : f(f) {}
void Run() { f(); }
private:
Func f;
};
template<typename Func>
MyClass<Func> MakeMyClass(Func&& f)
{
return { std::forward<Func>(f) };
}
int main()
{
auto x = MakeMyClass( [](){} );
x.Run();
}
Somehow I need to implement lazy evaluation with c++ variadic lambda. I am not quite sure whether the following code works correctly.
template <typename... ArgsT>
auto lazy_pack(ArgsT&& ... args) {
auto T = [&](bool condition) {
if(condition == false) return;
Foo v(std::forward<ArgsT>(args)...);
v.do_work();
};
return T;
}
The question is, how do I capture a given argument list and perfectly forward them to another templated object? The above example compiles but I am worried about if any dangling reference might happen. Another way is to capture arguments through copy and them and pass to the object:
template <typename... ArgsT>
auto lazy_pack(ArgsT&& ... args) {
auto T = [=](bool condition) {
if(condition == false) return;
Foo v(args...);
v.do_work();
};
return T;
}
I'm not sure I got what you are looking for, but maybe the following code can help you:
#include <tuple>
#include <functional>
#include <cstddef>
#include <utility>
#include <iostream>
struct Foo {
Foo(int v, const char *s): val{v}, str{s} { }
void do_work() { std::cout << val << " " << str << std::endl; }
int val;
const char *str;
};
template<std::size_t... I, typename... ArgsT>
auto lazy_pack(std::index_sequence<I...>, ArgsT&&... args) {
return [tup{std::forward_as_tuple(std::forward<ArgsT>(args)...)}](bool condition) {
if(condition == false) return;
Foo v(std::get<I>(tup)...);
v.do_work();
};
}
template<typename... ArgsT>
auto lazy_pack(ArgsT&& ... args) {
return lazy_pack(std::make_index_sequence<sizeof...(ArgsT)>(), std::forward<ArgsT>(args)...);
}
int main() {
auto l = lazy_pack(42, "bar");
l(false);
l(true);
}
You need at least one more helper function to be able to unpack later the parameters forwarded to the first one.
I was trying to work on the below code but the program crashes:
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef void (*callBackMethod)(string);
class CTest
{
private:
map<string, callBackMethod> mapMethod;
void testMethod(string msg)
{
cout << msg << endl;
}
public:
CTest()
{
addFunction("AA", (callBackMethod) &CTest::testMethod);
}
void addFunction(string funName, callBackMethod methodName)
{
mapMethod[funName] = methodName;
}
callBackMethod getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
return 0;
}
I have a requirement where I need to pass private methods to a map. The program compiles with warning:
converting from 'void (CTest::*)(std::__cxx11::string) {aka void (CTest::*)(std::__cxx11::basic_string<char>)}' to 'callBackMethod {aka void (*)(std::__cxx11::basic_string<char>)}'
and when I execute this, it crashes.
When I move the callback method outside of the class it works. My requirement is to make the program flow this was (hide the methods from external call which needs to be added to a map).
Looking forward to your comments.
If you need to point to both CTest member functions and free functions, then you can use std::function<void(std::string)>.
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
using callBackFunction = std::function<void(string)>;
void testFunction(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
class CTest
{
private:
map<string, callBackFunction> mapMethod;
void testMethod(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
public:
CTest()
{
addFreeFunction("AA", testFunction);
addMemberFunction("BB", &CTest::testMethod);
}
void addMemberFunction(string funName, void(CTest::*methodName)(string))
{
using std::placeholders::_1;
mapMethod[funName] = std::bind(methodName, this, _1);
}
void addFreeFunction(string funName, void(*methodName)(string))
{
mapMethod[funName] = methodName;
}
callBackFunction getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
test.runFunction("BB");
return 0;
}
Notice that CTest must insert elements into the map in a different way depending on what type of function you are passing, since for member functions you must provide the object for which it is to be invoked, this in this example. This is achived by using std::bind.
Since you want to use member variables you need to specify the signature differently in your typedef:
In C++ Builder the following can be done:
typedef void(__closure *callBackMethod)(string);
If you do that, I do suggest that you keep a smart pointer to the object that the member belongs to so that you can check if the object is still valid before calling the function otherwise it will crash the application.
The __closure keyword is a C++ Builder extension to work around the requirement to use fully qualified member names source
To handle both global and member functions we have the following:
typedef void(__closure *callBackMethodMember)(string);
typedef void (*callBackMethodGlobal)(string);
/* And then on 2 overloaded functions */
void addFunction(string funName, callBackMethodMember methodName) {}
void addFunction(string funName, callBackMethodGlobal methodName) {}
I have to implement A valve Open function (for specified duration).
I am using boost::asio::deadline_timer
My class member function to open valve is:
bool Valves::valveOpen(ValveType type)
{
switch (type)
{
case eVentValve:
tblMap_.digitalInput[eVentValveK1].setBit();
if (tblMap_.digitalOutput[eOutK1VentValve].getBit())
{
isVentOpen_ = true;
}
return isVentOpen_;
case eVacuumPumpValve:
....
....
}
Class member function to close the valve is:
bool Valves::valveClose(ValveType type)
{
switch (type)
{
case eVentValve:
tblMap_.digitalInput[eVentValveK1].clearBit();
if (!tblMap_.digitalOutput[eOutK1VentValve].getBit())
{
isVentOpen_ = false;
}
return !isVentOpen_;
case eVacuumPumpValve:
....
....
}
I am trying to achieve the timer action as below
bool Valves::valveTimedOpen(ValveType type, int sec)
{
boost::asio::io_service io;
switch (type)
{
case eVentValve:
{
std::bind(&Valves::valveOpen, this, type); //Here
boost::asio::deadline_timer t(io, boost::posix_time::seconds(sec));
t.async_wait(std::bind(&Valves::valveClose, this, type));
boost::thread th(boost::bind(&boost::asio::io_service::run, &io));
return true;
}
case eVacuumPumpValve:
.....
.....
}
The code hits the line Here i.e.
std::bind(&Valves::valveOpen, this, type); but it does not go to bool Valves::valveOpen(ValveType type) function.
Can someone let me know the issue with this code?
Variables io and t go out of scope as soon as valveTimedOpen exits. You need to rethink the way you interact with the boost asio components e.g. the io_service could be a member of your class, and the timer could be dynamically allocated and needs to be deleted in the completion handler.
Also, keep in mind that if you plan on re-using an io_service object, you also need to reset it before calling run again.
auto fn = std::bind(&Test::Open, shared_from_this(), std::placeholders::_1);
fn(type);
Calls the Open() correctly.
io_service and boost::deadline_timer I have to make class member as suggested by #Ralf
Working Code:
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
class Test : public std::enable_shared_from_this <Test>
{
public:
Test() :io(), timer(io){}
void Open(int num);
void Close(int num);
void TimedOpen(int num, int dur);
void Run();
private:
boost::asio::io_service io;
boost::asio::deadline_timer timer;
};
void Test::Open(int num)
{
std::cout << "Open for Number : " << num << std::endl;
}
void Test::Close(int num)
{
std::cout << "Close for Number : " << num << std::endl;
}
void Test::TimedOpen(int num, int dur)
{
io.reset();
auto fn = std::bind(&Test::Open, shared_from_this(), std::placeholders::_1);
fn(num);
timer.expires_from_now( boost::posix_time::seconds(dur));
timer.async_wait(std::bind(&Test::Close, shared_from_this(), num));
Run();
std::cout << "Function Exiting" << std::endl;
}
void Test::Run()
{
boost::thread th(boost::bind(&boost::asio::io_service::run, &io));
}
int main()
{
auto t = std::make_shared<Test>();
t->TimedOpen(5, 5);
char line[128];
while (std::cin.getline(line, 128))
{
if (strcmp(line, "\n")) break;
}
return 0;
}