0

I'm trying to handle winsock's addrinfo pointer with the unique_ptr. After doing some research I found an answer that wasn't really explained very well, so now I'm confused. (The answer I'm talking about: Smart pointers with addrinfo struct)

So my general understanding of unique_ptr says that the syntax is as follows: unique_ptr<type of handled data, type of function deleting the data>(pointer, deleter function pointer);.

A basic example of this would be:

void deleteInt(int* ptr){...}

int* ptr = new int;
unique_ptr(int, void(*)(int*)>(ptr, deleteInt);

Note how the function type doesn't specify a name and simply has (*).

Now, finally, onto my question: In the answer I mentioned above, the code does something weird. Instead of being unique_ptr<addrinfo, void(*)(addrinfo*)>... it is unique_ptr<addrinfo, void(__stdcall*)(addrinfo*)>... and nobody seems to question it. How so? How does it change the type of the function? What is __stdcall? Why does it even work since T (name*)() isn't even valid syntax? Needless to say, simply having void(*)(addrinfo*) as the function type doesn't work and spits out a bunch of incomprehensible template errors which I don't understand.

Rokas Višinskas
  • 533
  • 4
  • 12

1 Answers1

1

__stdcall is a calling convention, which controls how function parameters are passed, how the call stack is cleaned up, etc. Your int* example does not specify a calling convention for its deleter, so the compiler's default calling convention is used (usually __cdecl). But API functions have defined calling conventions for interop purposes, so you must use the correct convention. Almost all Win32 APIs (with few exceptions) use the __stdcall calling convention.

Rather than hard-coding the deleter's type, it would be easier to use decltype instead and let the compiler deduce the type for you:

addrinfo *addr;
getaddrinfo(..., &addr);
unique_ptr<addrinfo, decltype(&::freeaddrinfo)> addrPtr(addr, &::freeaddrinfo);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks for the informative answer, I didn't know that such a thing even existed. Could you also elaborate on what it means to use decltype with `&::`? I have never seen it used in such a way. – Rokas Višinskas Jan 25 '19 at 21:00
  • @Habitate `&` is the address-of operator, and `::` is the scope operator. The code is taking the address of the `freeaddrinfo` function that is located in the global namespace. – Remy Lebeau Jan 25 '19 at 22:30
  • Thanks for the heads up, I was a little bit confused about the `&` operator since I thought using a simple function name is the same as passing the pointer. Seems not to be the case with `decltype`. – Rokas Višinskas Jan 26 '19 at 09:09