1
votes

I have the following code using Boost ASIO to setup a TCP client. Here is my code adapted from the Boost doc's chat example.

class AsioCommunicationService {
AsioCommunicationService::AsioCommunicationService(
        boost::asio::io_service& io_service,
        tcp::resolver::iterator endpoint_iterator)
    : io_service_(io_service),
      socket_(io_service)
{
    tcp::endpoint endpoint = *endpoint_iterator;
    socket_.async_connect(endpoint,
    boost::bind(&AsioCommunicationService::handle_connect, this,
    boost::asio::placeholders::error, ++endpoint_iterator));
}

void AsioCommunicationService::handle_connect(const boost::system::error_code& error,
        tcp::resolver::iterator endpoint_iterator)
{
    if (!error)
    {
      boost::asio::async_read(socket_,
          boost::asio::buffer(read_msg_.data(), LampMessage::header_length),
          boost::bind(&AsioCommunicationService::handle_read_header, this,
          boost::asio::placeholders::error));
    }
}
}


class Connection
{
    //init io_service, query, resolve, iterator here
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::resolver resolver(io_service);
    boost::asio::ip::tcp::resolver::query query(host, service);
    boost::asio::ip::tcp::resolver::iterator endpoint_iterator =
  resolver.resolve(query);


    m_session = std::shared_ptr<AsioCommunicationService>(
            new AsioCommunicationService(io_service, iterator));

    //start new thread for io_service.run --> GOT AN ERROR when include boost/thread.hpp
    boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));

    //this synchronous command would work, but it's blocking the program. I don't want that.
    //io_service.run();
}

Of course, I needed to include boost/thread to make the declaration to variable t in class Connection works. But when I did so, I got this error

#include <boost/thread.hpp>
//ERROR: In function ‘boost::thread&& boost::move(boost::thread&&)’:
///usr/include/boost/thread/detail/thread.hpp:349:16: error: invalid initialization of reference of type ‘boost::thread&&’ from expression of type ‘boost::thread’
//In file included from /usr/include/boost/thread/detail/thread_heap_alloc.hpp:17:0,
//             from /usr/include/boost/thread/detail/thread.hpp:13,
//             from /usr/include/boost/thread/thread.hpp:22,
//             from /usr/include/boost/thread.hpp:13,
//             from /home/son/dev/logistics/src/frameworks/networkService/NetworkConnection.cpp:13:
///usr/include/boost/thread/pthread/thread_heap_alloc.hpp: In function ‘T* boost::detail::heap_new(A1&&) [with T = boost::detail::thread_data<void (*)()>, A1 = void (*&)()]’:
///usr/include/boost/thread/detail/thread.hpp:130:95:   instantiated from here
///usr/include/boost/thread/pthread/thread_heap_alloc.hpp:24:47: error: cannot bind ‘void (*)()’ lvalue to ‘void (*&&)()’
///usr/include/boost/thread/detail/thread.hpp:43:13: error:   initializing argument 1 of ‘boost::detail::thread_data<F>::thread_data(F&&) [with F = void (*)()]’

It would compile and work if I remove the include to boost/thread.hpp, and replace the declaration to t by a simple call to io_service.run(); I'm wondering if this compilation error has to do with boost version. I'm using Boost ASIO 1.42, Ubuntu 11.04 and Eclipse if those are of any help. Thank you in advance.

3
Can you try to strip this down to a small self-contained example, so people can experiment with it? - MvG
Boost 1.42 is quite dated (from 2010 afaics). At least some of the error messages refer to rvalue references, which are part of the C++11 standard and must have been pretty bleeding edge at that time. There might still have been a number of rough edges. I'd try a recent version of boost and see whether that solves your problems. - MvG
thanks @MvG, basically I got those errors when I put the include <boost/thread.hpp> in my code. The rest doesn't concern I think. - Son Do Lenh

3 Answers

3
votes

I wrote a single file containing a single include directive:

#include <boost/thread.hpp>
  • g++-4.5.4 -std=c++0x -I /usr/include/boost-1_42 -c gave the errors you mention.
  • g++-4.6.3 -std=c++0x -I /usr/include/boost-1_42 -c the same
  • g++-4.7.1 -std=c++0x -I /usr/include/boost-1_42 -c gave even more errors
  • g++-4.7.1 -std=c++0x -I /usr/include/boost-1_49 -c has not a single error
  • g++-4.6.3 and g++-4.5.4 also work without error using boost 1.49

So I'd really suggest you use a more recent version of boost for this. You don't have to install it system-wide, but instead can install it for a single user. So you are not dependent on ubuntu packages.

To manually install boost, I suggest you follow the Getting Started on Unix Variants guide:

  1. Untar boost_1_50_0.tar.bz2 to some temporary source directory and cd into that
  2. Build and install using ./bootstrap.sh --prefix=${HOME}/boost_1_50 && ./b2 install
  3. Compile your application using -I ${HOME}/boost_1_50 to get correct headers
  4. Include ${HOME}/boost_1_50/lib/libboost_thread.a as an argument when linking your application

Using the static libboost_thread.a as opposed to the dynamic libbtoost_thread.so will ensure that you don't have to worry about locating libraries to launch your application. Everything from boost which you need will be included in your main binary.

1
votes

Following the line of reasoning of @MvG of C++11 standard, I did some research. It seems that it's a problem of coordination between gcc and boost provided with Ubuntu Natty, which used -std=c++0x and libboost1.42, respectively.

There's no solution for it, but I used this workaround: commenting out # define BOOST_HAS_RVALUE_REFS in /usr/include/boost/config/compiler/gcc.hpp as follows.

#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__)
// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are
// passed on the command line, which in turn defines
// __GXX_EXPERIMENTAL_CXX0X__.
# define BOOST_HAS_DECLTYPE
//# define BOOST_HAS_RVALUE_REFS
# define BOOST_HAS_STATIC_ASSERT
# define BOOST_HAS_VARIADIC_TMPL
#else

My code compiles like magic now:) Thanks @MvC.

0
votes

After much exploration, following @MvG suggestion, I successfully compiled and linked my simple program by doing the following:

  • manually build and install boost 1.50 (using MvG suggestion)
  • compile and link the source using the following 2 make files (1 for static and 1 for dynamic linking).

Dynamic:

default: test

test.o: test.cpp
    g++-4.5 -std=c++0x -I /home/son/boost_1_50/include/ -c test.cpp 

test: test.o        
    g++-4.5 -std=c++0x -L /home/son/boost_1_50/lib/ test.o -lboost_thread -lboost_system -lboost_chrono -pthread -o test

run: test
    LD_LIBRARY_PATH=/home/son/boost_1_50/lib/ ./test

Static:

default: test

test.o: test.cpp
    g++-4.5 -std=c++0x -I /home/son/boost_1_50/include/ -c test.cpp 

test: test.o
    g++-4.5 -std=c++0x -L /home/son/boost_1_50/lib/ test.o -static -lboost_thread -lboost_system -lboost_chrono -pthread -o test

run: test
    ./test

The test.cpp file is as follows.

#include <boost/thread.hpp>
#include <stdio.h>

int main()
{
    printf("boost thread tested by son\n");
    boost::thread t;
    return 0;
}

That's it. I'm having difficulties compiling this with CMake but that's another problem.