Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ difference between function declaration and object initialization

Tags:

c++

c++11

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.

like image 750
Elvis Dukaj Avatar asked Dec 04 '22 13:12

Elvis Dukaj


2 Answers

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.

like image 183
Kerrek SB Avatar answered May 10 '23 23:05

Kerrek SB


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)

like image 21
David Rodríguez - dribeas Avatar answered May 10 '23 23:05

David Rodríguez - dribeas