开发者

"Could not deduce template argument" error when using Winsock bind() call with Boost

I'm fairly new to C++, and I'm likely in over my head, but that's the way it goes.

I'm working with a fairly large Win32 C++ project that uses Winsock for its network communications. I'm in the process of trying to convert a bunch of its thread management over to boost, but once I added the references to the boost libraries and what-not, I'm getting about 30 errors on this particular line of code:

bind(mLocalSocketFd, (struct sockaddr *) &localServerAddress, sizeof(localServerAddress));

The errors include things like:

error C2602: 'std::tr1::_Result_of2<_Fty,_Farg0,_Farg1>::_Type' is not a member of a base class of 'std::tr1::_Result_of2<_Fty,_Farg0,_Farg1>'
error C2868: 'std::tr1::_Result_of2<_Fty,_Farg0,_Farg1>::_Type' : illegal sy开发者_开发百科ntax for using-declaration; expected qualified-name
error C2784: 'bool std::operator <(const std::vector<_Ty,_Ax> &,const std::vector<_Ty,_Ax> &)' : could not deduce template argument for 'const std::vector<_Ty,_Ax> &' from 'std::tr1::_Bind_fty<_Fty,_Ret,_BindN>' 
error C2784: 'bool std::operator <(const std::vector<_Ty,_Ax> &,const std::vector<_Ty,_Ax> &)' : could not deduce template argument for 'const std::vector<_Ty,_Ax> &' from 'std::tr1::_Bind_fty<_Fty,_Ret,_BindN>'

I presume that somehow I've managed to tell this particular file ("NetServer.cpp") to use the boost version of bind(), but for the life of me, I can't figure out where that's happening. The only portion of boost that I'm using is the boost/thread.hpp, and I'm not doing any namespace using's anywhere in NetServer.cpp or in the header files that it links to.

Any suggestions as to what I'm doing wrong, or how to troubleshoot it? It's obviously some stupid newbie thing, but I can't figure it out.


There's a Boost function called bind() which is a totally different thing from Winsock's bind().

You have two options if you need both functions available in a given module:

  1. Don't say "using namespace boost". Instead, explicitly qualify uses of Boost in your code. I prefer this option since Boost is a third-party library and its short names may conflict both with other third-party libraries and with future versions of C++ that adopt Boost features. Occasionally I will say "using namespace boost" within a single function if it contains several uses of Boost.

  2. Explicitly qualify the use of the global Winsock bind():

    ::bind(mLocalSocketFd, ...


As you can see from MSVC's cryptic error message, your bind call goes to std::tr1::bind.

So, probably you're using namespace std;.

As @Warren Young indicated, ::bind will direct your call to the unqualified bind identifier - which then is WinSock's in your case.


I've just encountered the same issue, and found an official Microsoft answer here: http://connect.microsoft.com/VisualStudio/feedback/details/500364/how-to-avoid-conflicts-between-tr1-bind-and-winsock-bind-function

Short version: Even if you are not calling boost namespace, I guess you have a using namespace std somewhere, and since I guess you are using VS2010, it has the tr1 extension, so using namespace std acts like using namespace boost for the bind() function with VS2010.

If you ever have anything call using namespace std in advance then

you make all of the names in namespace std available to unqualified name lookup. Therefore, both Winsock's bind() and 's bind() are considered during overload resolution, and because 's bind() is a template, it will usually win, but fail to compile later.

Solution:

To fix this, call ::bind() when you want Winsock's bind(), and std::bind() if you ever want 's bind(). When you call ::bind(), you're asking the compiler to look in the global namespace only.

Or alternatively, don't use namespace std.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜