As noted by this question, boost::asio now can use the C++11 chrono objects if they are available. However, the following code compiles with but not with clang 3.6.0-svn223366-1~exp1
#include <iostream>
#include <boost/chrono.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <chrono>
#include <thread>
#include <functional>
boost::asio::io_service ioservice;
boost::asio::steady_timer timer(ioservice);
void function()
{
std::cout << "Success" << std::endl;
}
int main()
{
std::thread t([&]{ ioservice.run(); });
t.detach();
timer.expires_from_now(std::chrono::milliseconds(10));
timer.async_wait(boost::bind(&function));
std::this_thread::sleep_for(std::chrono::seconds(1));
}
gcc:
~/scratch$ g++ -std=c++11 test_asio_chrono_broken.cpp -lpthread -lboost_system -lboost_chrono
~/scratch$ ./a.out
Success
gcc and boost are happy to use std::chrono
However, clang:
~/scratch$ clang++-3.6 -std=c++11 test_asio_chrono_broken.cpp -lpthread -lboost_system -lboost_chrono
test_asio_chrono_broken.cpp:23:8: error: no matching member function for call to 'expires_from_now'
timer.expires_from_now(std::chrono::milliseconds(10));
~~~~~~^~~~~~~~~~~~~~~~
/usr/include/boost/asio/basic_waitable_timer.hpp:414:15: note: candidate function not viable: no known conversion from 'std::chrono::milliseconds' (aka 'duration<int64_t, milli>') to 'const duration' (aka 'const duration<boost::int_least64_t, nano>') for 1st argument
std::size_t expires_from_now(const duration& expiry_time)
^
/usr/include/boost/asio/basic_waitable_timer.hpp:387:12: note: candidate function not viable: requires 0 arguments, but 1 was provided
duration expires_from_now() const
^
/usr/include/boost/asio/basic_waitable_timer.hpp:445:15: note: candidate function not viable: requires 2 arguments, but 1 was provided
std::size_t expires_from_now(const duration& expiry_time,
^
1 error generated.
boost::asio is trying to use boost::chrono instead of std::chrono.
Who is at fault here? I would guess that boost is to blame because it has special GCC #ifdef flags for catching c++11 and std::chrono, but that those #ifdefs aren't catching that std::chrono is available when using clang. To whom do I report this issue?
I can fix the code by explicitly defining the timer type (as required by older versions of boost before the automagic std::chrono detection was added). The following change will compile on both gcc and clang
typedef boost::asio::basic_waitable_timer<std::chrono::steady_clock> steady_timer;
steady_timer timer(ioservice);
The chrono documentation describes this
Support for the std::chrono facilities is automatically enabled for g++ 4.6 and later, when the -std=c++0x or -std=gnu++0x compiler options are used. (Note that, for g++, the draft-standard monotonic_clock is used in place of steady_clock.) Support may be disabled by defining BOOST_ASIO_DISABLE_STD_CHRONO, or explicitly enabled for other compilers by defining BOOST_ASIO_HAS_STD_CHRONO.
Added emphasis is mine. That said, you can get this working using clang by explicitly defining BOOST_ASIO_HAS_STD_CHRONO
clang++ -D BOOST_ASIO_HAS_STD_CHRONO -std=c++11 test_asio_chrono_broken.cpp -lpthread -lboost_system -lboost_chrono
I don't know if there is precedence supporting clang for stuff like this in other boost libraries, please file a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With