to me concepts and coroutines really reduce the amount of boilerplate needed.
- just the ability of doing
if constexpr(requires { T::some_member; }) { ... }
to check if a type has a member variable / function / whatever makes code infinitely clearer than the previous mess requiring overloads.
- coroutines finally enable to properly abstract the data structures used by a type's implementation, e.g. you don't need to spill out anymore that your type stores stuff in std::vector or std::array or boost::small_vector or std::list etc etc to client code, and they simplify async code very well. for instance with Qt: https://qcoro.dvratil.cz/reference/core/qprocess/#examples
- three-way comparison and automtic generation of comparison / equality function is really great for removing needless boilerplate
- void f(auto arg) { ... } instead of template<typename T> void f(T arg) { ... }
- foo{.designated = 123, .init = "456" }; (although it was already more or less supported on every relevant compiler for years