4 ms·
I recently came back to write a small experiment in C++. I programmed it professionally for a decade, ending in 2002, and was pretty good at it. After the last
by hughw 10y ago
I recently came back to write a small experiment in C++. I programmed it professionally for a decade, ending in 2002, and was pretty good at it. After the last 16 years working in Java, Scala, Clojure, and Javascript, I have two observations on C++ 11:
a) Grateful for the extensive access to algorithms, lambdas, type inference;
b) Astounded at the complexity of template meta programming.
I imagine I'll get better at it with practice. But I'm operating at about 15% of the time efficiency of, say, Scala.
- AstralStorm 10y agoWhy do you really need to do template metaprogramming? Generally that is not required even in performance sensitive code. Perhaps a few conditionals a'la enable_if or direct use of SFINAE... but most everything else, not really.
- hughw 10y agoI needed to create a custom iterator for Thrust, a STL/Boost-like library for CUDA.
- hughw 10y agoAdditionally: I needed to make a program to join two tables by a common subset of their columns. It's desirable in CUDA, to enhance caching locality, to work with structs of arrays rather than arrays of structs. So a pattern in Thrust is to work with tuples. You zip up your columns and then you can use them in transformations. That's nice enough. The trouble arises when you need to write code to join (and transform) table A having NA columns, by table B having NB columns, sharing some number of shared columns NC. To manipulate the tuples you end up specializing cases and you build some awful large switch statements. That is, if you're a naive rookie, like me. Then you back off, and try to learn a little meta programming. You actually can dynamically treat tuples, sort of like lists, a little bit. But finally I decided that too is a kind of madness, and I'm on my third try, this time using a custom iterator over good old-fashioned dynamic vectors of arrays, so I can sidestep tuples altogether, and still use the structure of arrays idiom.
- hughw 10y agoOh -- and enable_if, and SFINAE -- these are terms I've learned only in the last three weeks, but yes, I would count having to learn even those concepts, to successfully use the language, as an obstacle and not for the faint of heart, right?
- int_19h 10y agoGenerally speaking, you don't have to know them unless you're writing generic libraries in the vein of STL and Boost. If you're just using those, then SFINAE etc is the magic under the hood that makes it all "just work".
- mannykannot 10y agoSooner or later you will likely be faced with having to understand code that was written by someone who had just learned about template metaprogramming and was determined to put his new-found knowledge to use.
- hughw 10y agothat's gonna be the next guy who looks at this code i'm writing... Edit: Clarification, I am not actually having myself to do original metaprogramming, but in order to diagnose problems implementing the custom iterators, I have needed to delve into, and understand, the meaning of the Thrust library code.
- mannykannot 10y agoYou ask way too many pertinent questions to be the sort of person who does what I am thinking of.
- sqeaky 10y agoThere is a simple trick to using complex template meta-programming techniques correctly: Leave it up to library authors. It sounds tongue in cheek, but I am serious. In the std library, boost and other sophisticated libraries there are tons of template shenanigans and there is little to be gain for most application developers. The single thing complex template meta-programs buy you is compile time evaluation for things in the middle of algorithms and classes. Which is useful, but usually for things like deciding how many object should be allocated at once or how big a working set is to keep everything in cache. These are usually the performance optimizations you care about after all the algorithmic ones have been dealt with and often save only a constant number of instructions. When this seemingly insane level of optimization makes sense the author of a library will often accept the needed data as a parameter. With constexpr things like lookup tables can easily be computed at compile with much more sane code.
- Animats 10y ago"You are not expected to understand this", the language. (When it breaks, then you have to.)
- sqeaky 10y agoIf that were true then every javascript coder would need to "understand" every javascript runtime. And every Ruby coder would need to understand C in case their libraries break. Every Java programmer would need to know the implementation of their JVM. Every ... In practice when the tools we rely on break, we have other alternatives. We tend to start with web searches and asking questions on SO. We can try different versions or libraries. Most problems have workarounds that may or may not be applicable. Sometimes deep knowledge helps and I will tend to advocate for it. In the case of template metaprogramming, deep knowledge gains you very little and a common breakage will add 2 extra instructions to your runtime execution. If that matters you are already watching for it. As soon as you use COM, RPC, a web API or any scripting language you have already done something that would blow this cost away for an abstraction. Knowing enough to fix a problem doesn't always mean a deep understanding of every library and tool even in C and C++ land. There is simply too much for any 1 person or any dedicated team to know, we must rely on division of labor. That is why we find abstractions like COM, RPC, web APIs and scripting languages worthwhile, they allow someone else to handle some part of our cognitive load at the cost of runtime performance.