Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> It's a huge reminder C++ is missing a proper, hygienic, macro system.

Templates, man.



In case someone reads this comment as sarcasm: I got into a convo with Stroustrup about this once, back in the 90s. I said one thing I missed was the lack of macros, and he made a glancing comment about the preprocessor which I obviously dismissed and said didn’t even count. He bitterly said, “Yeah, unfortunately when something like that pollutes an ecological niche it becomes impossible to eradicate. The best I could get away with was templates.”

A good perspective.


Bjarne was right, although C++ has been slow to adopt replacements for the preprocessor (such as modules, and conditional compilation).


I'm standing by for the announcement that some caffeine-addled Boost metaprogramming madman has implemented the Rust borrow checker as a C++ template, or at least thinks that he may have, when the compilation completes sometime in the 2030s.



It's not clear how much boost.org magic they used. Failing that, a GCC extension could be needful.

From the ref:

---

Conclusion

We attempted to represent ownership and borrowing through the C++ type system, however the language does not lend itself to this. Thus memory safety in C++ would need to be achieved through runtime checks.

Example code

#include <type_traits>

#include <utility>

#include <assert.h>

#include <stddef.h>


Why use template metaprogramming? You can use compiler extensions for that since the code will be valid either way


C++ has the Maximum Pain Rule.

Templates it must be.


There is a branch of clang with support for "-Wlifetime" which might be a simpler alternative.


It is not like I didn't try...


Don't forget function templates! D can do them, too, but we strongly discourage their use. The trouble is that people use them to create DSLs that are indistinguishable from C++ code. For example:

    #include <boost/spirit.hpp>
    using namespace boost;
    int main() {
      spirit::rule<> group, fact, term, expr;
      group   = '(' >> expr >> ')';
      fact    = spirit::int_p   | group;
      term    = fact >> *(('*' >> fact) | ('/' >> fact));
      expr    = term >> *(('+' >> term) | ('-' >> term));
      assert( spirit::parse("2*(3+4)", expr).full );
      assert( ! spirit::parse("2*(3+4", expr).full );
    }
https://studylib.net/doc/10029968/text-processing-with-boost... slide 40

What's C++ and what's regex?


Aren't these just normal parser combinators?


A >> means right shift, except when it doesn't in the example.


Yes, obviously operations with parser combinators are different that those with numbers. (Also, I find it kind of dumb to reserve short symbols for low-level operations that are rarely used in normal programming.)


Well, the problem here is the re-use of existing operators.

(That's why it's great that Haskell and other languages in that family allow you to define your own operators, instead of eg re-using bit-shifting for IO.)


Defining your own operators means combining the lexer with the semantic analysis, which comes with all sorts of complexities.


Actually, no. At least the way it's handled in Haskell and OCaml avoids this problem.

(Btw, parsing C++ is already Turing complete.)


Templates are nice, but they have shortcomings a more generic macro system wouldn't. They also have the issue where the more complex is your task, the more convoluted the code has to look, compilation times also increase and parsers (ergo, IDEs too) have trouble giving meaningful info on parameters. Don't even get me started on template errors because that's an atrocity on another level :(


The problem with no info on parameters and horrible template errors are related:

The root cause is that template expansion is duck-typed. 'Concepts' are supposed to fix that, I heard.


Can it be used to implement automatic serialization on simple struct / class types?


If you only use std::tuple, then yes xD


There is a nasty trick which uses structured binding to convert an arbitrary aggregate to a tuple.

That still doesn't help if you want the fields names.


You have any link?



Thanks. This may be useful for me someday.


No, because C++ templates are basically a Lisp, and only things that are list-like can be processed by templates. (Like tuples, for example.)


That's a bit confusing. Lisp has all kinds of datatypes.

But you are right that C++ templates are a bad functional programming language with duck typing.


But there are automated ways to to convert aggregates to tuples.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: