41

Alternative tokens are valid c++ keywords, yet in Visual Studio 2013 the following emits a compilation error (undeclared identifier):

int main(int argc, const char* argv[])
{
    int k(1), l(2);
    if (k and l) cout << "both non zero\n";

    return 0;
}

Since and or not have been around for quite some time, is there a reason for not implementing them?

yoozer8
  • 7,361
  • 7
  • 58
  • 93
Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
  • 1
    What is the error message _exactly_? –  Jun 25 '14 at 16:36
  • I'm wondering **why** is that. It can't be implementation complexity and if they're afraid to break old code the same should apply for gcc et al. A simple grep/replace would resolve any of their codebase conflicts, so is there a deeper reason, is there a dispute behind the scenes or just a feature that nobody cared enough to ask? – Nikos Athanasiou Jun 25 '14 at 16:43
  • @NikosAthanasiou A simple grep/replace would probably mess up a lot of comments. – D Drmmr Jun 25 '14 at 19:03
  • 1
    GCC is generally *much* more cavalier about breaking old code in the name of standards conformance than MSVC is. – zwol Jun 26 '14 at 00:12

5 Answers5

29

You ask about the rationale. Here's one possible reason, not necessarily the one that most influenced the Visual C++ team:

  1. Those are valid identifiers in C.
  2. Microsoft's recommendation has long been to use C++ mode for both C and C++ code, rather than maintaining a modern C compiler.
  3. Valid C code using these as identifiers would gratuitously break if they were compiled as keywords.
  4. People trying to write portable C++ are mostly using /permissive- or /Za for maximum conformance anyway, which will cause these to be treated as keywords.
  5. The workaround to treat them as keywords in /Ze by including a header file is easy and portable. (G++'s workaround -fno-operator-names isn't bad either, but putting the option in the source code rather than the build system is somewhat nicer.)
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 1
    Could you amend the `/Za` part, please? Apparently it’s very buggy and Microsoft discourages its use (though not in the documentation of course, grrr). See https://www.reddit.com/r/cpp/comments/76pmky/til_c_has_and_or_and_not/dogao5m/ – Konrad Rudolph Oct 17 '17 at 10:46
  • Also as a note, ``/Za`` causes a bug in MSVC which triggers compiler errors when including ``windows.h``. I made a report about this since I encountered this issue after checking this post: https://github.com/SasLuca/MSVCBug/blob/master/README.md – BananyaDev Feb 07 '19 at 23:10
  • If you encounter problems with ``/Za`` just use ``/permissive-`` instead. – BananyaDev Feb 08 '19 at 11:37
17

VS is nonconforming. This is old news.

To use alternative tokens, include the <ciso646> header. According to the standard, including this header is supposed to have no effect in C++. However, you do need it in VS. So it's safe to just include it always, whenever there is any chance that you might be compiling with VS.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • 9
    As it has been already noted, this "non-conformity" is only specific to the default compilation settings. Most (if not all) compilers are no-conforming in default mode. Specifying the `/Za` option removes this non-conformity from VS compiler. – AnT stands with Russia Jun 25 '14 at 17:00
  • gcc with C++11 or later without the -pthreads option is another good example. – Johan Lundberg Oct 14 '17 at 12:15
14

Modern Visual Studio (or rather, MSVC) does support alternative tokens; however, it does so only in standards conformance mode. This mode comes with lots of goodies, so it should always be used.

To enable it, pass /permissive- to the compiler.


The answer below is obsolete. This is now supported, see above!

Previously, Microsoft’s position was1 that

#include of <iso646.h> (or ciso646) is how we support these keywords

And because “nobody” (before me, in 2007) ever requested this.

1 link currently defunct; left here for archival purpose.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
14

Formally, these keywords are implemented and are supported intrinsically by the compiler without including any headers. However, for that you have to compile your source code in "more standard" mode of that C++ compiler, which means using the /Za option.

By intent, the /Za option is supposed to "disable compiler extensions". Of course, not supporting something that is supposed to be there in a compliant compiler cannot be formally qualified as a "compiler extension". Yet, that just the way things currently are.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    Doesn't answer the question, which is "why?" – Ben Voigt Jun 25 '14 at 16:51
  • 1
    @Ben Voigt: Well, it thought the "why" part came from "why not implemented?". Such question is based on an incorrect premise, since they actually *are* implemented. – AnT stands with Russia Jun 25 '14 at 16:53
  • 2
    The "extension" is to let the programmer have these names as identifiers. – Ben Voigt Jun 25 '14 at 16:55
  • 5
    @Ben Voigt: Yes, but the formal definition of an "extension" clearly says that extensions are not allowed to break any compliant code. In other words, true extensions are allowed to "define what's undefined by the standard", but they are not allowed to "undefine (or redefine) what's already defined by the standard". Formally, extensions are allowed to *extend* the domain of compilable code, but not allowed to *shrink* it. – AnT stands with Russia Jun 25 '14 at 16:57
  • Sadly this is not actually an option for me because it results in lots of errors in standard headers such as `winnt.h(12723): error C2467: illegal declaration of anonymous 'struct'`. – nwp Sep 01 '20 at 10:02
3

(contemporary update)

I made a small test: A New "Windows Desktop Application" Project. The IDE (Visual Studio 2017 15.7.5) sets, by default, the following C++ language conformance settings: /permissive- /Zc:wchar_t /Zc:forScope /Zc:inline. In addition, I set the C++ Language Standard to ISO C++ /Latest draft (currently up to C++17). In addition, I added, in the main(), the following 2 lines:

bool a, b, c;

a = b and c;

It compiles the text-forms of the logical operators successfully. But when I altered the IDE Conformance mode to No (=> without /permissive-) and re-compile, the compiler marks: "error C2065: 'and': undeclared identifier".

By default, the /permissive- compiler option is set in new projects created by Visual Studio 2017 version 15.5 (December 2017) and later versions. It is not set by default in earlier versions. So if someone created a project prior to version 15.5 and by the time update the IDE to the latest version, still it required to set in the project this compiler option manually.

The /Ze compiler option, which is on by default, enables Microsoft extensions. The /Ze option is deprecated because its behavior is on by default. MSDN recommends to use the /Zc (Conformance) compiler options to control specific language extension features.

Amit G.
  • 2,546
  • 2
  • 22
  • 30