8

When I include the algorithm library before defining epsilon, the following code compiles:

#include <iostream>
#include <algorithm>

#define epsilon 0.00001

int main() {
    std::cout << epsilon; 
    return 0;
}

When I switch them around, it doesn't:

#include <iostream>

#define epsilon 0.00001

#include <algorithm>

int main() {
    std::cout << epsilon; 
    return 0;
}

It gives the following error 19 times:

epsilon_algorithm.cpp:3:17: error: expected unqualified-id before numeric constant
    3 | #define epsilon 0.00001
      |

On http://www.cplusplus.com/reference/algorithm/ and https://en.cppreference.com/w/cpp/algorithm there is no mention of anything named 'epsilon'. I know I can avoid the issue by simply always including <algorithm> before I define epsilon, I want to know what causes this error to broaden my understanding of C++ and prevent these types of errors in the future.

I compile with MinGW (32 bit, installed a few weeks ago) in an updated Windows 10 (64 bit) environment.

rvvermeulen
  • 169
  • 8
  • 3
    [here's an epsilon](https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon) – user253751 Jul 15 '20 at 14:07
  • 6
    Don't use `#define` for constants. `inline constexpr auto epsilon = 0.00001;` or something like that should be used instead. Most likely includes and limits does have `epsilon` in it. – NathanOliver Jul 15 '20 at 14:07

1 Answers1

15

Standard library headers are allowed to include any other standard library header.

It's possible that <algorithm> includes <limits> and there exists std::numeric_limits::epsilon() there. And of course macros ignore namespaces and classes, so it would try to declare a function called 0.00001.

Don't use macros. Use C++ constants:

constexpr double epsilon = 0.00001;

And if you absolutely need macro, always define them after all includes. Defining them before makes your code very brittle - any change in those headers in the future might blow up your code with cryptic compiler errors.
Don't define macros in header files, for the same reason.
Prefer very localized macros when possible - define them where needed and #undef after you are done. This way they won't leak to the outside (although you can still inadvertently override an existing macro).

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52