Exact source listing in Visual Studio 2015
//
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot
com)
//
// Distributed under the Boost Software License, Version 1.0. (See
accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <ctime>
#include <iostream>
#include <string>
#include
#include
#include
#include
#include <functional>
using boost::asio::ip::tcp;
std::string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time(0);
return ctime(&now);
}
class tcp_connection
: public boost::enable_shared_from_this
{
public:
typedef boost::shared_ptr pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
private:
tcp_connection(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
void handle_write(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
}
tcp::socket socket_;
std::string message_;
};
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
{
start_accept();
}
private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service());
std::function callback =
std::bind(&tcp_server::handle_accept, this, new_connection,
std::placeholders::_1);
acceptor_.async_accept(new_connection->socket(), callback);
}
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code& error)
{
if( !error )
{
new_connection->start();
}
start_accept();
}
tcp::acceptor acceptor_;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch( std::exception& e )
{
std::cerr << e.what() << std::endl;
}
return 0;
}
Exact output spew from compilation:
This is against boost 1.55, because that's what I have at home. I use
1.62.0 at work and get the exact same errors.
1> Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
1> - add -D_WIN32_WINNT=0x0501 to the compiler command line; or
1> - add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.
1> Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(1953):
warning C4996: 'WSAAddressToStringA': Use WSAAddressToStringW() instead or
define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(3556):
note: see declaration of 'WSAAddressToStringA'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(2159):
warning C4996: 'WSAStringToAddressA': Use WSAStringToAddressW() instead or
define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(3623):
note: see declaration of 'WSAStringToAddressA'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(2295):
warning C4996: 'gethostbyaddr': Use getnameinfo() or GetNameInfoW() instead
or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(2216):
note: see declaration of 'gethostbyaddr'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(2344):
warning C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead
or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(2238):
note: see declaration of 'gethostbyname'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_select_interrupter.ipp(62):
warning C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define
_WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(1850):
note: see declaration of 'inet_addr'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_select_interrupter.ipp(75):
warning C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define
_WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(1850):
note: see declaration of 'inet_addr'
1>d:\users\cpisz.christopherpisz\documents\visual studio
2015\projects\consoleapplication1\consoleapplication1\source2.cpp(27):
warning C4996: 'ctime': This function or variable may be unsafe. Consider
using ctime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
See online help for details.
1> c:\program files (x86)\windows
kits\10\include\10.0.10240.0\ucrt\time.h(475): note: see declaration of
'ctime'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\basic_socket_acceptor.hpp(1015):
error C2338: AcceptHandler type requirements not met
1> d:\users\cpisz.christopherpisz\documents\visual studio
2015\projects\consoleapplication1\consoleapplication1\source2.cpp(91):
note: see reference to function template instantiation
'boost::asio::async_result<Handler>::type
boost::asio::basic_socket_acceptor::async_accept&>(boost::asio::basic_socket
&,AcceptHandler,void *)' being compiled
1> with
1> [
1> Handler=std::function,
1> Protocol=boost::asio::ip::tcp,
1>
StreamSocketService=boost::asio::stream_socket_serviceboost::asio::ip::tcp,
1> AcceptHandler=std::function &
1> ]
1> d:\users\cpisz.christopherpisz\documents\visual studio
2015\projects\consoleapplication1\consoleapplication1\source2.cpp(91):
note: see reference to function template instantiation
'boost::asio::async_result<Handler>::type
boost::asio::basic_socket_acceptor::async_accept&>(boost::asio::basic_socket
&,AcceptHandler,void *)' being compiled
1> with
1> [
1> Handler=std::function,
1> Protocol=boost::asio::ip::tcp,
1>
StreamSocketService=boost::asio::stream_socket_serviceboost::asio::ip::tcp,
1> AcceptHandler=std::function &
1> ]
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\basic_socket_acceptor.hpp(1015):
error C2064: term does not evaluate to a function taking 1 arguments
1> d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\basic_socket_acceptor.hpp(1015):
note: class does not define an 'operator()' or a user defined conversion
operator to a pointer-to-function or reference-to-function that takes
appropriate number of arguments
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
& somehow got put there from copy pasting? It is an actual amperstand in
code.
I am posting via Gmail now. I am not sure if they did it. At work I have to
post through nabble, because they have just about everything blocked.
On Tue, Mar 28, 2017 at 9:23 PM, Gavin Lambert via Boost-users <
boost-users@lists.boost.org> wrote:
On 29/03/2017 12:02, Christopher Pisz via Boost-users wrote:
Sigh. I know that code wouldn't work. That is my interpretation of what
you
gave me. Now you are talking about two arguments and placeholders, but why
would I give it a place holder, when I am giving it the argument directly?
the tcp_connection::pointer argument is new_connection. The placeholder is
for the error code which I am not supplying directly. Either way, it still
fails to compile if you add a std::placeholders::_2 on the end.
You need _1 (and only that) in the functor that is passed to async_accept,
since that expects a callback that takes exactly one error_code argument.
You might need other placeholders if elsewhere you're using functors that
take more than one argument, as in one previous instance where you were
using multiple binds or getting a callback passed in externally to then
rebind locally.
Can we just get a compilable working example of the following method while
maintaining the use of the std::function variable? I don't want to bind
directly, I don't want to use lambda, I want to have an std::function
variable that I can pass to others. It's really a simple 6 line
problem....
Just be careful with passing functions outside of the class, as they can
have hidden dependencies (eg. the below will UB or crash if something tries
to call the callback after tcp_server has been destroyed).
The following code still fails to compile:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service());
std::function callback =
std::bind(&tcp_server::handle_accept, this, new_connection,
std::placeholders::_1);
acceptor_.async_accept(new_connection->socket(), callback);
}
I still can't see your monitor from where I'm sitting, so I don't know
what errors it produces. If you want anything more helpful than guesswork,
then tell people what the errors are; don't just say that it fails. (
http://www.catb.org/esr/faqs/smart-questions.html)
First off, is that & actually in your source code or is it only being
added when you email? You need to fix that if it's actually in your code.
Secondly, you shouldn't specify parameter names in the type signature of
std::function; just use types.
Otherwise, that code looks like it should work, assuming handle_accept has
a compatible signature.
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users