0

I'm trying to write some code that needs to compile/run in both visual studio and linux (gcc) environment. When I try to compile my file in windows I'm getting a somewhat ambiguous error, and I'm wondering if anyone can point me to what I'm missing... I have the standard macro:

#define __MAX(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })

And then when I try to invoke it:

        int x = __MAX(0, 2);

I get an expected an expression error in visual studio, pointing to this line. I'm new to visual studio, so I'm not sure what it's not liking about this. Can anyone point me to what I'm doing wrong?

user2766918
  • 574
  • 4
  • 17
  • 5
    Doesn't answer the question but why not use `std::min` and `std::max` which are 100% portable? – NathanOliver Sep 29 '16 at 17:56
  • @NathanOliver Unfortunately, `std::min` and `std::max` don't always work in Windows because `` has macros for `min` and `max` which will clash with it. Yeah, it's hilarious. IIRC, there's a macro to disable those if you define it before including ``. Either way, it sucks. – Mysticial Sep 29 '16 at 17:59
  • @NathanOliver No. `` defines macros named `min` and `max`. So they will substitute the macro into the `std::min` and turn it into `std:: a < b ? a : b` which is a syntax error. (http://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std) – Mysticial Sep 29 '16 at 18:03
  • @Mysticial Oh c***. Forgot about that one. Yeah total BS on MS for that. – NathanOliver Sep 29 '16 at 18:05
  • 2
    Just `#define NOMINMAX` before `#include ` and you are fine. – Timbo Sep 29 '16 at 18:06
  • Why are you setting extra variables? – neoaggelos Sep 29 '16 at 18:11
  • @Timbo is write. Just suppress the `` macros and use the standard inline functions, which get the subtle details right. Also, identifiers like `__MAX` are reserved by the compiler/standard libraries, so don't define your own versions of those. – Adrian McCarthy Sep 29 '16 at 18:19

2 Answers2

4

That typeof stuff is gcc specific. You don't have that stuff when compiling with cl.exe (microsoft's compiler that visual studio uses). https://social.msdn.microsoft.com/Forums/vstudio/en-US/984ae3e8-6391-45b9-8885-edb088da8bfa/will-msvc-support-a-typeof-operator-like-in-gcc?forum=vclanguage

Rob
  • 26,989
  • 16
  • 82
  • 98
Pavel
  • 1
  • 3
  • 17
  • 51
  • Link only answers are ugly (to keep the nice form saying that). – πάντα ῥεῖ Sep 29 '16 at 17:59
  • Thanks. I thought it was standard C, but guess not. I'll create a windows version of the macro. I don't suppose windows has a method to prevent duplicating side effects in macros? – user2766918 Sep 29 '16 at 18:12
  • @user2766918 if you want just C, you shouldn't have used the C++ tag in the first place. You can use gcc via mingw on windows, by the way. – Pavel Sep 29 '16 at 18:14
  • 1
    @user2766918 - If you mean anything with the C++ tag, you can use inline functions instead of macros. That avoids re-evaluating the parameters. – Bo Persson Sep 29 '16 at 18:14
  • The original program is written in C for a linux distribution. The visual studio version is using a C++ compiler though. This particular macro is used in shared code, so it needs to be compiled with both a C and a C++ compiler. It had occurred to me that when I was posting that this might be something c++ specific as opposed to visual studio specific, so I included a C++ tag. Since windows is using C++, I can replace the macros with inline functions in an `ifdef WINDOWS` – user2766918 Sep 29 '16 at 18:29
0

If the problem is that std::max and std::min don't work, because of macros, you can locally disable them, like so:

#define DONT_EXPAND_MACRO

template<template T>
const T mini(const T& a, const T& b)
{
    using std::min;
    return min DONT_EXPAND_MACRO (a, b);
}
chtz
  • 17,329
  • 4
  • 26
  • 56