Someone a few months ago told me that I had to change a bunch of code from stuff like this...

// config_options.h
// define _FOO if and only if you want option foo to be available
#ifndef _FOO
    #define _FOO
#endif

// main.cpp
#include "config_options.h"

#ifdef _FOO
void foo()
{
    cout << "foo\n";
}
#endif

to this...

// config_options.h
// define FOO if and only if you want option foo to be available
#ifndef FOO
    #define FOO
#endif

// main.cpp
#include "config_options.h"

#ifdef FOO
void foo()
{
    cout << "foo\n";
}
#endif

The reason, she said, was that Visual Studio, or whatever IDE I am using, might define _FOO for whatever reason on its own, thus interfering with my defining it in the .h file. She said that I should define or not define FOO for that reason because the IDE would never do that, but it might define _FOO. Someone else dittoed that, so I changed everything.

Then someone today said that that advice was 100% wrong and that it was better the first time and that the convention, for configuration / ini files where the user changes the code to allow or disallow options, a leading underscore is used to specify that this is a pre-processor name as opposed to, say, a constant.

Who is right?

Let's have a look at the C++ Standard, shall we:

Section 17.6.4.3.2/1:

Certain sets of names and function signatures are always reserved to the implementation:
— Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.
— Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

So, the first person was correct. Technically speaking, this only applies to global names (including pre-processor defines of MACROs), but to be on the safe side, you'd better avoid it altogether.

Then someone today said that that advice was 100% wrong and that it was better the first time and that the convention, for configuration / ini files where the user changes the code to allow or disallow options, a leading underscore is used to specify that this is a pre-processor name as opposed to, say, a constant.

There is no wide-spread convention that I know of that prescribes leading underscores for #defines. That guy pulled that out of his ... hat. You might see leading underscores in the standard library implementation provided by your compiler, but that's the point, it is reserved for the "implementation" (which means the compiler and its standard library implementation). You might see that in Boost libraries too, being the anti-chamber for standard libraries, it's just an exception to the rule.

You should not be using a name like _FOO anywhere in your code.

A name like _fOO can be used except in the global unnamed namespace. Just make sure that the character following the leading underscore is a lower case character.

This question has already been answered. Start a new discussion instead.