[G. Sliepen](/u/129343) already took care of the big picture issues, where you get the most bang for the buck. Still, there are a few issues with the code aside from using a sub-optimal algorithm: 1. You should consider [`std::string_view`](https://en.cppreference.com/w/cpp/string/basic_string_view) for the string-argument, and for getting a temporary slice of a long-lived string. Dynamic allocation is pretty expensive, and best avoided, both on calling a function if the input might not be in the desired format, and in the function itself. 1. Now that the functions no longer allocate memory, or contain any other potential exception-thrower, mark them `noexcept`. It won't do much of anything here, but is good documentation, informs the compiler if it only knows the declaration, and can be important later with using templated code consuming it for best performance and highest guarantees. 1. Also, mark them `constexpr` while you are at it, to allow encourage evaluation at compile-time and allow forcing that. Also a best-practice thing not actually changng much of anything for your example program itself. 1. You use `std::cout` twice (whyever you don't chain it all together escapes me), and `std::endl` once. The using-declaration doesn't look like a good investment, even if you dislike writing `std::`. 1. Don't force flushing a stream unless you really mean it. And in that case, better be explicit and use `std::flush`. Flushing is normally expensive buzy-work.