This code is not working
any idea why
#include <QCoreApplication>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "a.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
boost::asio::io_service io;
std::cout << "Wait for five seconds\n";
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
// t.wait();
A *vvv=new A();
std::cout << "Hello, world!\n";
t.async_wait(&print);
std::cout << "Keep cool and wait!\n";
return a.exec();
}
void print(const boost::system::error_code& /*e*/)
{
std::cout << "You are cool!\n";
}
Error:
D:\qtsrc\asiotry\main.cpp:14: error: C2065: 'print' : undeclared
identifier
Have a look at this code:
int *address = &i; //using i here!
int i; //declaration
What is wrong with this code? You're doing something similar.
Declare print before main() so you can use it in main():
//declaration
void print(const boost::system::error_code& /*e*/);
int main()
{
//use print here
}
//definition
void print(const boost::system::error_code& /*e*/)
{
std::cout << "You are cool!\n";
}
Note that all you're required to declare the function before its usage, that does not necessarily mean that the declaration must be above main(). You could as well do this also:
int main()
{
//declaration
void print(const boost::system::error_code& /*e*/);
//use print here AFTER the declaration!
}
Hope that helps you to understand the concept of declaration and usage. -)
Remember one thing. The declaration of a function should precede its reference(usage) in the program.
Either add this before main:-
void print(const boost::system::error_code& /*e*/);
OR
Define the function before main.
It's because when you use print in the async_wait call, it's not declared yet, so it doesn't know what print is.
There are two possible solutions to this:
Move the definition of the print function to above main.
Before using it, declare it as a prototype.
Related
Live On Coliru
#include <iostream>
#include <boost/asio.hpp>
#include <functional>
class printer
{
public:
printer(boost::asio::io_context& io)
: timer_(io, boost::asio::chrono::seconds(1))
{
timer_.async_wait(std::bind(&printer::print, this));
// timer_.async_wait([this]() {
// print();
// });
}
void print()
{
std::cout << "hello world" << std::endl;
}
private:
boost::asio::steady_timer timer_;
};
int main()
{
boost::asio::io_context io;
printer p(io);
io.run();
return 0;
}
I tried to replace the following line:
timer_.async_wait(std::bind(&printer::print, this));
with
timer_.async_wait([this]() {
print();
});
But it failed and the compiler reports the following errors:
main.cpp: In constructor 'printer::printer(boost::asio::io_context&)':
main.cpp:12:22: error: no matching function for call to 'boost::asio::basic_waitable_timer<std::chrono::_V2::steady_clock>::async_wait(printer::printer(boost::asio::io_context&)::<lambda()>)'
12 | timer_.async_wait([this]() {
| ~~~~~~~~~~~~~~~~~^~~~~~~~~~~
13 | print();
| ~~~~~~~~
14 | });
| ~~
Question> What is the correct way to rewrite the std::bind with lambda expression?
Thank you
Your lambda doesn't have the required signature.
Based the boost documentation, the callback takes a const boost::system::error_code& argument. std::bind lets you be a bit looser in the function signature (Why std::bind can be assigned to argument-mismatched std::function?), but lambdas need to be an exact match.
The following code seems to work for me
timer_.async_wait([this](auto const &ec) {
print();
});
Lets consider the next piece of code:
#include <iostream>
void print()
{
std::cout << "I feel void" << std::endl;
}
void (*func)();
func = print;
This does not compile, since "func does not name a type".
But I already declared about func's type. It's a function pointer that takes no arguments and returns void. Why do I need to name a type again?
Do I always have to initialize a function pointer when declaring it?
No.
However, you cannot have expression statements such as assignments in namespace scope.
you can do that in main! , you cant do that in namespaces:
void (*func)();
void print()
{
std::cout << "I feel void" << std::endl;
}
int main(int argc, char* argv[])
{
func = print;
return 0;
}
but if you want do that before main execution , you can try below code(I prefer dont use this , but it's helpful sometimes):
#include <iostream>
void (*func)();
void print()
{
std::cout << "I feel void" << std::endl;
}
class Initilizer
{
public:
Initilizer()
{
init();
}
static void init()
{
func = ::print;
}
};
Initilizer obj;
int main(int argc, char* argv[])
{
func(); /*Test func*/
return 0;
}
I'm getting an compilation error, related to std::invoke, and also another that can not specialize the template for invoke.
This is the code:
#pragma once
#include <thread>
#include <iostream>
#include <vector>
#include <string>
#include <chrono>
class ThreadLoader {
private:
unsigned int id;
void _loadFile(const std::string& filepath) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Loading " << filepath << "\n";
}
public:
static unsigned int counter;
ThreadLoader() {
id = counter;
counter++;
}
void loadFile(const std::string& filepath) {
std::thread t(&ThreadLoader::_loadFile, std::ref(filepath), this);
t.join();
}
friend std::ostream& operator<<(std::ostream& os, const ThreadLoader& t) {
return os << t.id << std::endl;
}
};
unsigned int ThreadLoader::counter = 0;
The error appears when I tried to call the loadFile function.
I already checked this. I think followed the accepted answer, however, the error persists. I think that I'm doing something wrong in std::thread t(&ThreadLoader::_loadFile, std::ref(filepath), this);, but I don't find what is it.
You have your parameters the wrong way round, it should be:
std::thread t(&ThreadLoader::_loadFile, this, std::ref(filepath));
I am trying to create a simple BoostTimer class which wraps deadline_timer's essential functions such as async_wait and cancel, so that my program just calls startTimer and killTimer, I have written following code
boosttimer.h
#ifndef __BOOST_TIMER__
#define __BOOST_TIMER__
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/chrono.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/function.hpp>
class BoostTimer{
public:
typedef boost::asio::deadline_timer deadline_timer;
typedef deadline_timer::duration_type duration;
typedef boost::function<void (boost::system::error_code, BoostTimer&)> handler_function;
BoostTimer(boost::asio::io_service& io_service, duration interval, handler_function handler);
~BoostTimer();
void startTimer();
void killTimer();
private:
deadline_timer _timer;
boost::asio::io_service& _ioService;
duration _interval;
handler_function _handler;
};
#endif
boosttimer.cpp
#include "boosttimer.h"
BoostTimer::BoostTimer(boost::asio::io_service& io_service, duration interval, handler_function handler) :
_timer(io_service),
_ioService(io_service),
_interval(interval),
_handler(handler)
{
}
BoostTimer::~BoostTimer()
{
}
void BoostTimer::startTimer()
{
_timer.expires_from_now(_interval);
_timer.async_wait(boost::bind(_handler, boost::asio::placeholders::error, boost::ref(*this))); //trying to pass placeholder argument but somehow it doesn't work
}
void BoostTimer::killTimer()
{
_timer.cancel();
}
timertest.cpp
#include <iostream>
#include <boost/asio.hpp>
#include "boosttimer.h"
//void timer_handler(const boost::system::error_code& /*e*/) // not able to take parameters
void timer_handler() //it runs fine without parameters
{
std::cout<<"timer function has been called" << std::endl;
}
int main(int argc, char* argv[])
{
boost::asio::io_service io_service;
BoostTimer timer(io_service,boost::posix_time::seconds(5), boost::bind(&timer_handler));
timer.startTimer();
io_service.run();
return 0;
}
My question is how can i pass parameters to my handler function from my BoostTimer class's startTimer function ? I tried it but I am missing something.
If you just want to pass arguments from the caller:
void timer_handler(std::string const& arg1, int arg2)
{
std::cout<<"timer function has been called with arg1='" << arg1 <<"', arg2=" << arg2 << std::endl;
}
int main()
{
boost::asio::io_service io_service;
BoostTimer timer(io_service,boost::posix_time::seconds(5), boost::bind(&timer_handler, "This is arg1", 42));
timer.startTimer();
io_service.run();
return 0;
}
See it Live On Coliru, output:
timer function has been called with arg1='This is arg1', arg2=42
To also pass ec and *this:
CAVEAT I think this seriously breaks any encapsulation and makes the whole class basically redundant. Consider not calling the completion handler in case of cancellation e.g. Also, let the caller bind the objects instances it requires (it's weird for the user-defined handler to require a reference to BoostTimer - that's tight coupling in the wrong direction)
void timer_handler(boost::system::error_code ec, BoostTimer& instance, std::string const& arg1, int arg2) //it runs fine without parameters
{
std::cout<<"timer function has been called with arg1='" << arg1 <<"', arg2=" << arg2 << " (" << ec.message() << ")\n";
}
int main()
{
boost::asio::io_service io_service;
BoostTimer timer(io_service,boost::posix_time::seconds(1), boost::bind(&timer_handler, _1, _2, "This is arg1", 42));
timer.startTimer();
io_service.run();
return 0;
}
See it Live On Coliru too, output:
timer function has been called with arg1='This is arg1', arg2=42 (Success)
I want my function running in a separate thread. I use Boost library and include like this in my main.cpp:
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
I want the thread start like this:
boost::thread ethread(Engine::function,info);
// info is an object from the class Engine and i need this in the
// function
My Engine class is in the func.h and the function looks like this:
void Engine::function(Engine info)
{
//STUFF
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
BTW: Is the sleep function for the thread right?
Every time I want to compile it gives me this error:
error C3867: "Engine::function": function call missing argument list; use '&Engine::function' to create a pointer to member
I tried to use &Engine::function in the thread and this error appears:
error C2064: term does not evaluate to a function taking 2 arguments
I also tried:
boost::thread ethread(Engine::function,info, _1);
Then this error appeared:
error C2784: "result_traits<R,F>::type boost::_bi::list0::operator [](const boost::_bi::bind_t<R,F,L> &) const"
Can someone help me with this? I only want to run the function beside the main thread.
You should use bind function to create functional object with pointer to class member function or make your function static.
http://ru.cppreference.com/w/cpp/utility/functional/bind
More detailed explanation:
boost::thread constructor needs pointer to a function. In case of normal functions syntax is simple: &hello
#include <boost/thread/thread.hpp>
#include <iostream>
void hello()
{
std::cout << "Hello world, I'm a thread!" << std::endl;
}
int main(int argc, char* argv[])
{
boost::thread thrd(&hello);
thrd.join();
return 0;
}
But if you need pointer to a function of class you have to remember that such functions have implicit parameter - this pointer, so you have to pass it also. You can do this by creating callable object with std::bind, or boost bind.
#include <iostream>
#include <boost/thread.hpp>
class Foo{
public:
void print( int a )
{
std::cout << a << std::endl;
}
};
int main(int argc, char *argv[])
{
Foo foo;
boost::thread t( std::bind( &Foo::print, &foo, 5 ) );
t.join();
return 0;
}