Awesome C++

I found this page recently: http://awesomecpp.com/

Some bits I found exciting:

They list a couple of neat testing frameworks as well, but I don’t think they’re likely worth switching to. We might be able to use one of the rapidcheck/quickcheck/autocheck things to do things like our autodiff and distribution tests.

Tagging @Matthijs, @syclik, @Bob_Carpenter

2 Likes

Why is this useful? Most of the time we need access to the same thing in many different places, so this would still require const & references.

Automagic code improvements sound nice, but I have no experience with those. Should this be a long-hanging free fruit, then sure.

Thanks, Sean! I’m going to watch the modern C++ video.

Regarding the pattern matching library, it’s nice that people are trying to get it into the language, but I’m afraid it’s not really worth using for writing a compiler unless it also works well with variant types and recursion. In particular, you want to be able to define functions on ASTs using pattern matching, right? You’d want to express things like

f = match(p,
      FORLOOP(_x, _x, _x), [](std::string name, AST lower, AST upper){std::cout << "We've found a loop over " << name << " from ";
f(lower);
std::cout <<  " to ";
f(upper);
std::cout <<".";},
      INTVAL(_x), [](int n){std::cout << n;},
....)

. I don’t get the impression this library lets you do that, sadly.

I think you would need to specialize their simple_match::customization::tuple_adapter (about halfway down the readme) for destructuring and binding custom types. If we had one AST node class with a field for the actual type of the node, this wouldn’t be too bad. It’d look something like:

f = match(p,
      AST("for", _x, _x, _x), [](auto name, auto lower, auto upper) { ... },
      AST("int", _x), [](int x){...},
)

Right, this isn’t useful if you are just constructing objects that refer to other objects in some global scope, like autodiff variables. It’s useful all other times, haha. Here is the slide on that topic:

It’s from 1:25 or so in the video above.

Honestly, this looks a bit too clever by half. This constructor is written under the assumption that one will definitely need a direct copy of its arguments, rather than needing to extract and save some other information from those arguments. If that assumption changes, then the function signature for that constructor may need to change. By contrast, sticking with the usual const &/&& avoids that problem, since it works regardless of whether a direct copy is needed or not.

You could say that about the entire language, in my opinion. As a newcomer to C++, I find the pass-by-value and move idea to be refreshingly simple compared with the const ref versions.

Does changing from pass-by-value to pass by const ref have any trickle-down effects? As far as I understand you can use them in exactly the same ways in the same places… but there are so many corner cases, I could be missing something.

That is a very good point.

It’s also confusing in the code. There were a couple places where people were doing that to copy a matrix into the function argument, and it’s not clear it’s not a typo from looking at the signature, because it doesn’t match everything else.

The patterns are half as clever as in functional languages, which makes them about ten times as clever as they should be for common use.

My opinion changed as I got more familiar with the patterns and appreciated the control. I just wish the preprocessor was faster and had better debugging support. And that data types were of fixed sizes and that there weren’t a bunch of undefined behavior in the spec.

Also a good point. Not that I can see.

I take it back. This is the worst part of C++. The object oriented stuff and template stuff play terribly together.

1 Like