Saturday, August 23, 2014

7 useful features in C++14

C++14 is an enhancement over C++11. Here are a few features that are immediately useful:
  1. std::make_unique - a factory function for unique_ptr (which should be the most popular smart pointer) akin to std::make_shared for std::shared_ptr (which shouldn't be the most popular smart pointer).
    #include <memory>
    
    class Foo {
    public:
      Foo(int n) { ... };
      ...
    };
    
    auto fooPtr = std::make_unique<Foo>(10);
    

  2. std::cbegin and std::cend, applied to STL containers give you const_iterators.

  3. std::shared_timed_mutex, a la boost::shared_mutex - a very important addition if you use a fair bit of synchronization. This provides the multiple-reader single-writer (MRSW) type of abstractions.

  4. Getting elements from a tuple by type (if there is a unique element of that type in the tuple).
    std::tuple<int, double, std::string> threeElems = std::make_tuple(1, 2.0, "Foo");
    auto strFoo = std::get<std::string>(threeElems);

    This works, but would have failed had there been two elements of type std::string in the tuple.

  5. Note  how we had to write the type of threeElems in the last example. If we  had used auto instead, its type would be deduced as std::tuple <int, char const*, double> because std::make_shared deduces the type of the  returned tuple using the types of the passed arguments. If you wanted  to use a string literal whose type would be deduced as std::string, you  must use an s suffix like this:
    auto threeElems = std::make_tuple(1, 2.0, "Foo"s);
    auto strFoo = std::get<std::string>(threeElems);
  6. Generic lambdas - essentially lambdas with a very succinct syntax that can be reused for multiple type. Takes a lot of crud away from writing lambdas.
    std::vector<foo> vec;
    std::for_each(vec.begin(), vec.end(), [](auto& elem) { std::cout << elem << '\n'; });

    The  key is the use of the auto keyword for the parameter types. You could  use multiple parameters, all declared auto, whose types are  independently deduced. How does this really help? First, you don't have to write:
    [](Foo& elem) { std::cout << elem << '\n'; }
    
    Also, you could cache a lambda in a generic context with minimal syntactic noise and reuse it for multiple types. Consider this:
    auto elemPrint = [](const auto& elem) { std::cout << elem << '\n'; };
    std::for_each(vecOfInts.begin(), vecOfInts.end(), elemPrint);
    std::for_each(vecOfStrs.begin(), vecOfStrs.end(), elemPrint);
    
    where vecOfInts, vecOfStrs, etc. all contain elements of different, unrelated type.

  7. Being  able to write function with an auto return type, without any trailing  decltype to compute the type. In C++11, you would write something like:
    auto foo(int x, double y) -> decltype(x + y)
    {
       return x + y;
    }
    You can now simply write:
    auto foo(int x, double y)
    {
       return x + y;
    }

    There are several more changes but these stand out in terms of immediate usefulness.

No comments: