2

I am trying to create a thread in order to send a message to an open socket. I am gettings 2 specific errors.

E0289: No instance of constructor "std::thread::thread" matches the argument list.

C2661: 'std::thread::thread' no overloaded function takes 2 arguments**

I have found similar posts about this but still cannot quite figure it out could really use some clarification.

#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;
}
walnut
  • 21,629
  • 4
  • 23
  • 59
Andy
  • 25
  • 3
  • Unrelated: I'm not sure it's such a good idea to `WSAStartup` and `WSACleanup` on each call. You probably only want to do this once in `main`. If not, [put it in an RAII wrapper](https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii) so that it always gets cleaned up no matter what. – user4581301 Nov 22 '19 at 22:44
  • I am not a specialist for VS, but looks like C++11 is not enabled – Slava Nov 22 '19 at 22:44

1 Answers1

2

Windows has a SendMessage macro that transparently switches between the SendMessageA and SendMessageW functions depending on whether unicode is enabled or not. This macro substitution is stomping your SendMessage function.

You can add

#undef SendMessage

anywhere after

#include <WS2tcpip.h>

but this may cause problems later. I think you're best off changing the name of your SendMessage function to something that doesn't collide.

TL;DR Version

Why is this a problem? Ambiguity. Let's hack this down to an 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();
}

After the Preprocessor, the program looks like

void SendMessageW(string /*message*/)
{
}

int main()
{
    string message = "Test";

    thread sendtoSocket (SendMessageW, message);

    sendtoSocket.join();
}

The compiler now has to figure out which SendMessageW overload it has to call for thread sendtoSocket (SendMessageW, message);, the asker's or the Win32 API function, and it can't. This causes the compiler to look for additional thread constructors and misleading diagnostics are produced.

Looking into what's up with that, we need an even simpler MCVE where there are no overloads for the templated function

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);
}

This results in meaningful diagnostics:

error C2672: 'test': no matching overloaded function found

error C2783: 'void test(FUNC &&,ARGS &&...)': could not deduce template argument for 'FUNC'

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Thank you it was this exact problem! I have also fixed the WSAStartup and WSACleanup. – Andy Nov 22 '19 at 22:54
  • @Andy a long time ago I found out the hard way that the `strlen` function was sometimes implemented as a macro for performance reasons. Lost half a day trying to figure out why `int strlen;` generated about a page of compiler errors and now agree wholeheartedly with the Macros Are Evil movement. – user4581301 Nov 22 '19 at 23:06
  • 2
    How does this not already cause errors in OP's `SendMessage` definition? It should either become non-sense or redefine the API function that is is mapping to. The MSVC error message also doesn't make any sense to me. Why is it not complaining about type mismatches, rather than giving the wrong statement that no overload accepts two arguments. – walnut Nov 22 '19 at 23:11
  • That's a darn good question, @uneven_mark . I'm not certain why we don't see more errors or ambiguity errors. I'll crank out a preproccessor file and see what I can see. – user4581301 Nov 22 '19 at 23:27
  • @uneven_mark macro substitution is exactly what you'd expect, so both Andy's and Microsoft's `SendMessageW` are declared. That should be sorted out by the differences in the parameters. Gotta be something else I'm missing in here. Have to move on to paid work, so I'm dropping it for now. – user4581301 Nov 22 '19 at 23:48