If i wrote this line of code:
std::thread t(EchoServer(socket));
How can the compiler interpret this instruction? It can be a function declaration or simply an initialization. I've the followinc code:
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/asio.hpp>
typedef boost::asio::ip::tcp::socket Socket;
auto socket_deleter = [] (Socket* s) {s->close(); delete s;};
typedef std::unique_ptr<Socket, decltype(socket_deleter)> socket_ptr;
class EchoServer {
public:
static void Listen(unsigned int port)
{
using namespace std;
using namespace boost::asio;
io_service ios;
// create an endpoint to listen to a certain port
ip::tcp::endpoint endpoint(ip::tcp::v4(), port);
cout << "Listening to TCP Socket on port " << port << " ..." << endl;
// Start opening a socket
ip::tcp::acceptor acceptor(ios, endpoint);
// this loop must be infinite... but we accept only 3 connections
auto socket = socket_ptr(new Socket(ios));
std::thread t(EchoServer(socket));
}
EchoServer(socket_ptr&& s) : m_socket(std::move(s))
{
}
void operator ()() const
{
}
private:
socket_ptr m_socket;
};
But the compiler give me the following warning:
C4930: 'std::thread t(EchoServer(socket))': std::thread t(EchoServer(socket)) function not called (was a variable definition intended?).
So how can I explain that this line is an object of type std::thread creation instead a function declaration.
UPDATE 1:
I'm using visual studio 2012 that don't support uniform initialization so I've changed the code from std::thread t((EchoServer(socket)));
to std::thread t((EchoServer(socket)));
but this time I've a compil time error that i don't understand:
error C2440: '<function-style-cast>': cannot convert from 'std::unique_ptr<_Ty,_Dx>' to 'EchoServer'
What am I missing?
UPDATE 2 I've probably have to understand better move-semantic the problem is with the declaration of socket_ptr. I've changed the code in this (ugly) way... but now compiles.
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
typedef boost::asio::ip::tcp::socket Socket;
auto socket_deleter = [] (Socket* s) {s->close(); delete s;};
/*
typedef std::unique_ptr<Socket, decltype(socket_deleter)> socket_ptr;
*/
typedef Socket* socket_ptr;
class EchoServer {
public:
static void Listen(unsigned int port)
{
using namespace std;
using namespace boost::asio;
io_service ios;
// create an endpoint to listen to a certain port
ip::tcp::endpoint endpoint(ip::tcp::v4(), port);
cout << "Listening to TCP Socket on port " << port << " ..." << endl;
// Start opening a socket
ip::tcp::acceptor acceptor(ios, endpoint);
// this loop must be infinite... but we accept only 3 connections
auto socket = new Socket(ios);
std::thread t((EchoServer(socket)));
}
EchoServer(socket_ptr s) : m_socket(s)
{
}
~EchoServer()
{
m_socket->close();
delete m_socket;
}
void operator ()() const
{
}
private:
socket_ptr m_socket;
};
Changine socket_ptr as a simple pointer instead of an unique_ptr the code works.
It's a function declaration. If you want to declare an object with direct initialization, you can use one of the following methods:
std::thread t(EchoServer { socket });
std::thread t { EchoServer(socket) };
std::thread t { EchoServer { socket} };
std::thread t((EchoServer(socket)));
Brace-initialization is unambiguously initialization, and in the last line you have a parenthesized expression, which cannot work as a function parameter declaration.
As you mentioned, there are two possible interpretations of that statement, but the standard explicitly mandates that in the case of this ambiguity the compiler has to interpret the statement as a function definition (dropping the extra set of parenthesis):
std::thread t(EchoServer socket);
If you want to force that to be the creation of a std::thread
you can add an extra set of parenthesis that make the statement not a valid function declaration:
std::thread t((EchoServer(socket)));
Use a different syntax for the initialization:
std::thread t = std::thread(EchoServer(socket));
Or since you are using C++11 you can use uniform initialization:
std::thread t{EchoServer(socket)};
The first two options are valid C++03, but in a C++11 compiler you should probably use the third option (and the use of std::thread
indicates that you are using C++11 features)
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