Underappreciated C++ Features

C++ is a great language. It has some problems for sure, but it also has some really neat features to help you write some fast code that doesn’t look completely hideous. Here are some of my favorite features that I don’t think get enough love.

Unnamed Types

These are a super nice way to add organization to the members of your class without needing to define a whole bunch of named types cluttering up your IDEs autocomplete. If a type never needs to be passed to a function and is really just there to group parameters together, unnamed type members are great.

 class Sprite 
    {
        ...
        private:
            struct 
            {
                unsigned uint8_t* bytes;
                uint32_t width, height;
            } imageInfo;
    }; 

I don’t really recommend using it for public interface things, but for keeping things internally arranged in a super tidy way.

Kind of an tangentially-related side note please use the explicitly sized integer types from <cstdint> if your code has any chance of ever being compiled for another platform. It will make everyone’s lives so much easier.

The C++ standard states that you can’t define a new type as a return type, but Microsoft’s compiler (MSVC) doesn’t really seem to care about that. The following code will not compile using any other compiler I tried, but using MSVC it compiles and works.

struct {
  bool success;
  int rounded;
  double precise;
} fetchNumber() {
  return { true, 42, 42.0 };
}

int main(char** argv, int argc) {
  auto result = fetchNumber();
  if(result.success) {
    if(result.rounded > 40) {
      std::cout << result.precise << std::endl;
    }
  }
  return 0;
} 

I realize talking about a really cool compiler specific quirk right after preaching about cross platform code is kinda odd, but this is probably the coolest noncompliance I’ve ever encountered.

Variadic Templates + Argument Unrolling

Ok so templates are cool. They’re probably the most powerful feature of C++ with the nonsense they let you figure out at compile time. I’ve also written some absolute garbage code with them, but that’s not what we’re here for.

Say hypothetically you’ve got a templated class that represents an array of constant size. You want to construct a new instance of that class that uses certain indices from that array to make a new array. Graphics programmers probably know this as swizzling but it could be used for other things. My implementation just happens to be called swizzle because I couldn’t think of a better name. Anyway, if you want that behavior, you can combine a few really neat C++ template tricky to make it happen.

template<unsigned int...I, unsigned int N = sizeof...(I)>
Vector<T, N> Vector::swizzle()
{
    return { {data[I]...} };
} 

Cool. You have the code now if you just want to copy paste that out, but if you want to understand it read on. There’s a lot to dissect, lets unpack this one neat trick at a time.

The first argument of the template (that represents every argument the user will actually pass) are unsigned integers that are the indices of the vector you want to use to build the new vector. The second is hidden from the caller calculated from the first, using the unrolling sizeof... operator to count the variadic arguments.

The return type is pretty easy, its going to be a vector of objects of the same type but the number of them is taken from that count parameter that the template calculated.

Ok the return statement, I know this looks weird but its not too bad (just kidding its pretty gross). This class has an initializer list constructor so the outer braces are to invoke that. The inner braces are forming an unrolled indexing into this Vector’s data. It helps me to think of what this is doing as building the comma-separated initializer list of values you’d normally feed to the constructor, where those values are accessed by unrolling the list of variadic arguments that I represents.

This may seem weirdly niche, but I have genuinely used this trick in a professional code base to really clean up the binding of function arguments and member functions.