
Is the C++ preprocessor still needed? - ingve
http://foonathan.net/blog/2017/05/08/preprocessor.html
======
Stenzel
I am missing the motivation to purge the preprocessor - only reason he gives
is the paradigm that the preprocessor is considered bad practice. I fail to
see why. The preprocessor is a useful tool that can save you time and make
code more readable and portable. Conditions at compile time guarantee that the
compiler is not subjected to a specific portion of code, and it offers the
only way to define a constant value without having an implicit type for that.
Considering the use of C/C++ outside pure computer programming, like embedded
systems or digital signal processing, where portability, code size and target
specific substitutions or optimisations matter, there is simply no reason and
no way to get rid of the preprocessor without breaking things. Sure you can
use it in obscure and wrong ways, but it is not the job of the language to act
as a nanny and prevent you from doing evil by restricting access to dangerous
toys.

~~~
foonathan
Author here, I didn't intend to give a motivation for purging it, many people
in the C++ community want to and I wanted to explore the feasibility of that
in the current status.

> like embedded systems or digital signal processing, where portability, code
> size and target specific substitutions or optimisations matter, there is
> simply no reason and no way to get rid of the preprocessor without breaking
> things.

It certainly is, I know embedded projects where they use template meta
programming to get an even more advanced code generator.

------
nachexnachex
C coder here (former pre-C++11 C++ as well).

Another point to mention (which I think adds to the conclusion) is that by
losing compatibility with the C preprocessor you'd lose compatibility with,
well, C.

This means breaking of both C++ code that uses C libraries legitimately and
"C++" code that's actually C with new/delete (or "the horror" as we put it).

~~~
ericfrederich
Maybe dropping compatibility with C is a good thing?

All other languages wanting to interface with C seem to be using libffi or
something. Currently C++ gets a shortcut, but in the future maybe it could go
through an FFI.

It'd still be compatible with C from libraries, just not source. Those
libraries would have to ship header files free of macros of course.

~~~
nachexnachex
I don't see how losing backwards compatibility would be a good thing _per se_.
Even if the preprocessor were considered a problem (which is disputed), it
could coexist with a new FFI system that could be implemented.

Losing backwards compatibility is usually a price to pay, not an objective. As
an example, Python 3k chose to lose partial compatibility to 2.7 in order to
change some parts of the language. While the user and maintainer community
still debates if the change itself was a good decision (a different discussion
IMO...), probably most will agree that the incompatibility bit has been and
will be for some time a source of pain.

------
mabynogy
I use the gcc preprocessor in Javascript (to avoid modules and tools like
browserify):

    
    
        out="out/make1.js"
        main="make1/main.js"
        gcc -C -E -H -P -nostdinc -undef -x c $main -o $out
        node --harmony $out $@

~~~
ndesaulniers
looked up these flags, since I didn't know all of them:

-C: compile but do not link (I think this is covered by -E)

-E: stop after running the preprocessor

-H: print the name of each header file included, indenting child #includes (what do you use this for? is it printed to stderr?)

-P: inhibit the generation of line markers from the preprocessor (I've used this before, but can't recall the problem it solves? Not expanding __LINE__?)

-nostdinc: do not search standard system directories for header files (/usr/include, /usr/local/include, ..., this is standard in the Linux kernel, since there is no libc)

-undef: do not predefine any system-specific or GCC macros (probably to not expand occurrences of sequences like "__GNUC__" and others from unexpectedly being expanded).

-x <language>: specify the language, rather then letting the compiler guess based on the file extension (is this required?)

~~~
Goopplesoft
Thanks. Also, this site also seems to have args from man pages:
[https://explainshell.com/explain?cmd=gcc+-C+-E+-H+-P+-nostdi...](https://explainshell.com/explain?cmd=gcc+-C+-E+-H+-P+-nostdinc+-undef+-x+c+%24main+-o+%24out)

~~~
ndesaulniers
That's a neat utility! Thanks for sharing.

------
jordigh
I have to comment on this, even though it's almost completely irrelevant to
the blog post. I saw "do_sth" so I wanted to check where the writer was from.
Germany. Aha. :-)

I love how reliably abbreviating "something" (e.g. "sth", "smth" or "sthg")
indicates that the person isn't from an English-speaking country. I wonder why
this abbreviation has never caught on in English-speaking countries. I think
the abbreviations got popularised in non-English-speaking countries by English
dictionaries.

I think the more common idiomatic "abbreviation" would be "do_stuff" when you
don't want to type out or say "something".

~~~
tannhaeuser
Similarly OT, a pet peeve of mine is how Germans and others consistently
pronounce (the eg. SQL datatype) VARCHAR as var-CHAIR or sometimes var-CZAR
(war czar, warczaw) when they pronounce CHAR/CHR correctly.

~~~
bastih
That's because the English language is a mess with respect as to how something
is pronounced.

~~~
w8rbt
Great point! The words... their, mare, hair, where... all rhyme in English.
This drives Spanish speakers crazy.

------
codemac
The year is 2017 - is anyone worried about the preprocessor?

I feel it's largely worked out, and is well understood.

------
astrodust
Modules are massively over-due. A faster pre-processor processor wouldn't hurt
either.

~~~
CyberDildonics
Faster pre-processor? What makes you think that is the bottleneck?

tcc can fully compile all 6MB of sqlite in 1/100th of a second.

~~~
astrodust
SQLite is C, and C header files tend to be trivial in comparison to their
template-loaded C++ counterparts. Even though Firefox is only a few orders of
magnitude bigger in terms of source code it takes exponentially longer still
to compile.

~~~
CyberDildonics
And you think the preproccesor is a bottleneck in C++ ?

------
Jimmy
If you want to keep compiling any existing C++ code, then the answer is "yes".

------
hossbeast
After reading about all the hoops the author is willing to jump through to
avoid using the preprocessor, I was expecting the conclusion to be, yes, it
turns out we still need it.

~~~
foonathan
The conclusion is "yes, we still need it".

------
Taniwha
The thing is all people don't use C++ the same way - I've often found myself
using a small amount of C++ mixed with large amounts of C written by others -
my use of C++ needs to live with other's C headers, their #defines and
#includes - my use of C++ is no more or less valid than your's

BTW cpp is not slow, not compared with other parts of C++ compilers

------
yongjik
> The function std::experimental::source_location::current() expands to the
> information about the source file at the point of writing it.

Hmm, okay, and what happens when someone puts that thing _in a macro_?

Some macros can be horribly ugly, but I'm not sure replacing __FILE__ with
compiler-supported magic is an improvement.

~~~
WalterBright
> replacing __FILE__ with compiler-supported magic

D doesn't have a preprocessor, and so that's just what it does:

[http://dlang.org/spec/traits.html#specialkeywords](http://dlang.org/spec/traits.html#specialkeywords)

------
jimjimjim
oh god, please don't add more stuff to the language.

~~~
goalieca
Since c++11 I can't think of an enhancement that hasn't been beneficial.

~~~
EGreg
Lambdas. Concepts. Ten types of casts. Templates of templates. Everything and
the kitchen sink is in there.

You need a language lawyer to figure out anything but the most basic
interactions. For example,

1\. What's the practical difference between an abstract class and an
interface?

2\. When do you have a copy constructor run instead of a cast on
initialization if both are defined?

3\. When would you use a non-virtual destructor?

What happens when you hire people? Isn't it better to have a small language
that everyone understands in its entirety, and has to go out of their way to
surprise you?

~~~
wfunction
> 1\. What's the practical difference between an abstract class and an
> interface?

Interface? You _are_ talking about the C++ language, right?

~~~
kobeya
The funny thing is I just good faith assumed that this was some new feature
being added in C++17 that I'd now have to figure out how to use.

------
rwmj
OCaml doesn't have a C-style preprocessor, but I sometimes wish it did have
one. One case is where a function has changed its type signature, eg. adding a
parameter, but you still want to be able to write code that can compile with
the old and new versions of the library. It would be quickest to write:

    
    
        #if HAVE_OLD_LIB
            f 1 2;
        #else
            f 1 2 3;
        #endif
    

The actual solution in pure OCaml is a huge pain. Usually you have to add
another module which is conditionally compiled.

Luckily in OCaml you can write ‘ocamlopt -pp cpp’ to use the C preprocessor on
selected files.

------
partycoder
You would break many libraries starting by boost.

------
daemin
I'm wondering if anyone has tried to use another language - I'm thinking Ruby
- as a pre-processor for C++ code. I know people have pre-processed C++ code
with various tools - for example Qt - but I'm thinking of just replacing #
pre-processor statements with something like Rails based templates.

~~~
Pete_D
A while ago, in a fit of defmacro-envy, I wrote a preprocessor that would let
you wrap Python snippets in #python/#endpython blocks:
[http://codepad.org/5B388Wsh](http://codepad.org/5B388Wsh). This lets you
write silly things like
[http://codepad.org/eS443WPA](http://codepad.org/eS443WPA). I bet the same
idea isn't too hard to implement in Ruby, but I don't know enough to try it
myself.

I never really used it much - generating C code with Python print statements
turned out to look uglier than I thought it would, and most of my use cases
were better handled with X macros
([https://en.wikipedia.org/wiki/X_Macro](https://en.wikipedia.org/wiki/X_Macro))
or by generating a separate file and #include'ing it. But your description
reminded me of it; you might like the idea.

------
ericfrederich
Deprecate it now and it'll disappear in 20 years.

If CopperSpice was able to do it with a project as big as Qt it should be
possible for any project.
[http://www.copperspice.com/presentations.html](http://www.copperspice.com/presentations.html)

------
frozenport
Modules change the behavior of includes

------
pantalaimon
When I read things like
[https://twitter.com/sebrose/status/858347156427636738](https://twitter.com/sebrose/status/858347156427636738)

I wonder two things.

\- What does that even mean?

\- Why is this needed when I can do well without all that in C?

~~~
Const-me
A code that runs at compile-time, and verifies some restrictions about
classes. Namely, this one implements a class called “interface” so you can
create your stuff based on that, and verifies that your interfaces don’t
contain any data members or non-public functions.

It’s useless for me as well, but for different reason. I code for Windows, and
Microsoft’s compiler has __interface keyword for decades:
[https://msdn.microsoft.com/en-
us/library/50h7kwtb.aspx](https://msdn.microsoft.com/en-
us/library/50h7kwtb.aspx)

------
qb45
> don’t use it for inline functions

That's a myth afaik. Is there any standard way besides macros to really ensure
the code will be inlined? In particular, the suggestively named _inline_
keyword just doesn't work like that.

~~~
foonathan
There are attributes like `[[gnu::always_inline]]` for GCC and clang.

~~~
qb45
Yes, but they aren't portable.

You can work around this using per-compiler macros, which I guess is another
reason why CPP is to stay.

------
mailslot
Yes, but I don't know if you're talking about the C++ (templates and
constexpr's & whatnot) or the C preprocessor. Macros? Get rid of those and you
kill my logging solution.

------
tunnuz
Also, with #pragma once (practically supported by every compiler toolchain) we
don't need to do the if-not-defined-include trick.

~~~
llukas
Not if you do embedded.

~~~
CamperBob2
What does "embedded" have to do with anything? #pragma once works fine in gcc-
arm-none-eabi.

~~~
fnj
I think he means you may not have #pragma once available in every embedded
compiler. Embedded compilers are a mixed bag; gcc is a standout.

~~~
com2kid
Even ARM's embedded cortex-m compilers have supported #pragma once for years
now.

Maybe some of the 8-bit micros still don't..?

~~~
fnj
Didn't you ever have to program a Persistor 68332 with an ancient version of
CodeWarrior? How about CCS C for the 18F PIC?

~~~
com2kid
Thankfully no, M0s nearly come in cracker jack boxes now days. A lot of what
used to be on 8bits are moving to M0s because why the heck not.

Commercially advertised prices are around 60 cents in bulk, corporate buys in
the 100s of thousands are going to be cheaper than that. Death to 8bits! :)

------
lacampbell
Well until C++ develops an implementation of schemes _syntax-rules_ \- I hope
it stays.

------
flamedoge
sometimes I'd use C macro just because it's so darn hard to write capturing
lambda code in C++. But capture lambda is suppose to be better and safer. I
should use it more.

~~~
Const-me
When I do that, I just type [](){} first, then start filling whatever I need
in between those things.

------
surrey-fringe
[https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headline...](https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headlines)

~~~
gjm11
I think a more accurate version of Betteridge's law says: when a headline asks
a question, the answer is always _the less surprising_ answer. It just happens
that usually the more attention-grabbing way to write the headline is the one
that makes "no" the less surprising answer.

The Betteridge-compliant version of this article would have been titled "Can
we do without the C++ preprocessor?".

~~~
surrey-fringe
That's the joke. Made me laugh anyway.

