#Obscure (Possibly) function calling style

48 messages ยท Page 1 of 1 (latest)

elder willow
#

Why do some people call functions like this: auto v = (std::max) (4,6);?

Is there like any specific behaviour that can only be achieved by writing it like this?

sharp solsticeBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

civic cypress
#

the reason is to handle naughty code that uses macros

#

in particular, #include <Windows.h> is infamous for defining a macro spelt max(a,b)

#

so if you did auto v = std::max(4, 6) then it turns this into auto v = std::((4) > (6) ? (4) : (6)) which is obviously wrong

#

instead, by doing (std::max)(4, 6) then max( isn't seen by the preprocessor so the macro isn't expanded

long crest
#

Indeed ^, windows is usually to blame here which is why you'll see this with min/max specifically. In general though, foo(1, 2) and (foo)() will be the same for a normal function.

civic cypress
#

otherwise, the other difference is to do with a thing called "ADL"

elder willow
#

But isn't there a way to undef max so it doesn't conflict?

civic cypress
#

Yup, you can

#

And in fact you can #define NOMINMAX before including <Windows.h> and that also prevents it defining the macro

#

but in some contexts people can't be sure that someone else might not have included <Windows.h> before them and are later relying on the max macro existing

#

so this way works regardless

elder willow
civic cypress
#

there aren't many, it's specifically min and max that are the main problem children

fluid torrent
#

isn't it UB to include the standard library with max defined

civic cypress
#

well, there are many, but most of them are stuff like CreateWindow which are less likely to be accidentally used

elder willow
civic cypress
#

again, occasionally useful, typically not relevant don't worry about it if you don't understand ๐Ÿ˜›

elder willow
fluid torrent
civic cypress
#

yeah, in general you can't protect against it

#

min and max are just very common (because of <Windows.h>)

#

so people bother for those cases

elder willow
#

What is ADL BTW?

civic cypress
#

argument-dependent lookup

fluid torrent
#

it means that it will look up names in the namespaces of the types of the arguments

civic cypress
#

basically, doing foo(a, b, c), it looks up foo both in your current scope, but also in all the namespaces that a, b, and c are defined in

civic cypress
#

the details are a little more complex but that's the idea

fluid torrent
long crest
random junco
#
#include <iostream>
namespace ns {
  struct S {};
  int foo(S) { return 1; }
}

template <typename T>
int foo(T) { return 2; }

int main() {
  std::cout << foo(ns::S{}) << '\n';    // prints 1
  std::cout << (foo)(ns::S{}) << '\n';  // prints 2
}
old waveBOT
#
Program Output
1
2
random junco
#

wow this is weird

fluid torrent
#

SDL does #define main SDL_main

random junco
#

what is the reason behind ADL

elder willow
random junco
#

looks like a easy way to lose track of what you use

civic cypress
#

it's also used for other customisation points, e.g. begin and end for container-like types

#

or swap

fluid torrent
#
std::cout<<"abc";```for example this finds the appropriate function overload in `std::operator<<` to call
elder willow
#

!solved