试图创建一个线程来向套接字发送消息。遇到与线程构造函数有关的 2 个错误
Posted
技术标签:
【中文标题】试图创建一个线程来向套接字发送消息。遇到与线程构造函数有关的 2 个错误【英文标题】:Trying to create a thread to send a message to a socket. Getting 2 errors having to do with thread constructor 【发布时间】:2019-11-22 22:31:51 【问题描述】:我正在尝试创建一个线程以向打开的套接字发送消息。我收到 2 个特定错误。
E0289: 没有构造函数“std::thread::thread”的实例与参数列表匹配。
C2661: 'std::thread::thread' 没有重载函数需要 2 个参数**
我找到了关于此的类似帖子,但仍然无法完全弄清楚是否真的可以使用一些澄清。
#include <WS2tcpip.h>
#include <string>
#include <thread>
using namespace std;
#pragma comment (lib, "ws2_32.lib")
void SendMessage(string message)
WSAData data;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &data);
if (wsOk != 0)
cout << "Failed, Error Code: " << WSAGetLastError() << endl;
sockaddr_in user;
user.sin_family = AF_INET;
user.sin_port = htons(3514);
inet_pton(AF_INET, "127.0.0.1", &user.sin_addr);
SOCKET out = socket(AF_INET, SOCK_DGRAM, 0);
int sendMsg = sendto(out, message.c_str(), message.size() + 1, 0, (sockaddr*)&user, sizeof(user));
if (sendMsg == SOCKET_ERROR)
cout << "Failed, Error: " << WSAGetLastError() << endl;
closesocket(out);
WSACleanup();
int main()
string message = "";
cout << "Enter a message to send: ";
cin >> message;
thread sendtoSocket (SendMessage, message);
sendtoSocket.join();
system("pause");
return 0;
【问题讨论】:
不相关:我不确定每次通话时给WSAStartup
和WSACleanup
是否是个好主意。您可能只想在main
中执行此操作一次。如果没有,请put it in an RAII wrapper,这样它无论如何都会被清理干净。
我不是VS专家,但是好像没有启用C++11
【参考方案1】:
Windows has a SendMessage
macro 根据是否启用 unicode 在SendMessageA
和SendMessageW
函数之间进行透明切换。这个宏替换会影响您的 SendMessage
函数。
你可以添加
#undef SendMessage
之后的任何地方
#include <WS2tcpip.h>
但这可能会在以后引起问题。我认为您最好将 SendMessage
函数的名称更改为不会发生冲突的名称。
TL;DR 版本
为什么会出现这个问题?模棱两可。让我们将其分解为MCVE。
#include <WS2tcpip.h>
#include <string>
#include <thread>
#include <iostream>
using namespace std;
void SendMessage(string /*message*/)
int main()
string message = "Test";
thread sendtoSocket (SendMessage, message);
sendtoSocket.join();
经过预处理器后,程序看起来像
void SendMessageW(string /*message*/)
int main()
string message = "Test";
thread sendtoSocket (SendMessageW, message);
sendtoSocket.join();
编译器现在必须弄清楚它必须为thread sendtoSocket (SendMessageW, message);
、询问器或Win32 API 函数调用哪个SendMessageW
重载,但它不能。这会导致编译器寻找额外的线程构造函数并产生误导性诊断。
看看这是怎么回事,我们需要一个更简单的 MCVE,其中模板化函数没有重载
void A(int )
void A(double )
template<typename FUNC, typename... ARGS>
void test(FUNC&& func, ARGS&&... args)
func(args...);
int main()
int message = 10;
test(A, message);
这会产生有意义的诊断:
错误 C2672:“测试”:找不到匹配的重载函数
错误 C2783: 'void test(FUNC &&,ARGS &&...)': 无法推导出 'FUNC' 的模板参数
【讨论】:
谢谢,正是这个问题!我还修复了 WSAStartup 和 WSACleanup。 @Andy 很久以前我发现strlen
函数有时出于性能原因被实现为宏。花了半天时间试图弄清楚为什么 int strlen;
会生成大约一页编译器错误,现在完全同意 Macros Are Evil 运动。
这怎么不会导致 OP 的 SendMessage
定义出现错误?它要么变得毫无意义,要么重新定义映射到的 API 函数。 MSVC 错误消息对我来说也没有任何意义。为什么它不抱怨类型不匹配,而不是给出没有重载接受两个参数的错误声明。
这是一个非常好的问题,@uneven_mark。我不确定为什么我们没有看到更多错误或歧义错误。我会制作一个预处理器文件,看看我能看到什么。
@uneven_mark 宏替换正是您所期望的,因此声明了 Andy 和 Microsoft 的 SendMessageW
。这应该通过参数的差异来解决。一定是我在这里想念的其他东西。必须继续从事有偿工作,所以我暂时放弃了。以上是关于试图创建一个线程来向套接字发送消息。遇到与线程构造函数有关的 2 个错误的主要内容,如果未能解决你的问题,请参考以下文章