An Overview of C++26: The Library

An Overview of C++26: The Library

In my last post, I overviewed C++26’s core language. Today, I continue with the library.


To make it short. The library does not offer such powerful features as the core language. Let me name them and give you a short example directly from the proposal.

std::string and std::string_view Processing

The functions around std::string and std::string_view makes using them more convenient.

Testing for success or failure of <charconv> functions

Using the functions to_chars or from_chars was pretty inconvenient. You had to check with res.ec == std::errc{} the success of the conversion. With C++26, you can convert the result directly to bool.

Arithmetic overloads of std::to_string and use std::format

std::to_string has a few issues. The “choice of the floating-point format makes std::to_string of very limited use in practice” (P2587R3).

auto loc = std::locale("uk_UA.UTF-8");
std::locale::global(loc);
std::cout.imbue(loc);
setlocale(LC_ALL, "C");

std::cout << "iostreams:\n";
std::cout << 1234 << "\n";
std::cout << 1234.5 << "\n";

std::cout << "\nto_string:\n";
std::cout << std::to_string(1234) << "\n";
std::cout << std::to_string(1234.5) << "\n";

setlocale(LC_ALL, "uk_UA.UTF-8");

std::cout << "\nto_string (uk_UA.UTF-8 C locale):\n";
std::cout << std::to_string(1234) << "\n";
std::cout << std::to_string(1234.5) << "\n";
        


The program shows that the output of floating point overloads is inconsistent for iostreams. It takes the decimal point from the global C locale.

Interfacing stringstreams with std::string_view

Thanks to proposal P2495R3, you can create a stringstream from a std::string_view. In the following example, ""sv is an empty string_view literal.

// implicitly convertable to string_view
const mystring str;

stringstream s1(""sv);
stringstream s1(str);
s2.str(""sv);
        

Concatenation of strings and string views

With C++26, you can concatenate strings and string viewsString-Views:

std::string calculate(std::string_view prefix)
{
  return prefix + get_string(); // NO ERROR
}
        

Format Extensions

Pointers

Before C++26, only void, const void, and std::nullptr_t pointer types are valid. If you want to display the address of an arbitrary pointer, you must cast it to (const) void*.

double d = 123.456789;
std::format("{}", &d); // ERROR
std::format("{}", static_cast<void*>(&d)); // okay
std::format("{}", static_cast<const void*>(&d)); // okay
std::format("{}", nullptr); // okay
        

With C++26, the error messages disappear.

?

Modernes C++ Mentoring

Do you want to stay informed: Subscribe.

?

// pointerFormat.cpp

#include <format>
#include <iostream>

int main() {
 
    std::cout << '\n';

    double d = 123.456789;

    std::cout << std::format("{}", static_cast<void*>(&d)) << '\n';
    std::cout << std::format("{}", static_cast<const void*>(&d)) << '\n';
    std::cout << std::format("{}", nullptr) << '\n';

    std::cout << '\n';

}        

Here’s the output of the program.


std::filesystem::path

std::format can display std::filesystem::path objects. The example from the proposal P2845R8 shows.

auto p1 = std::filesystem::path("/usr/bin");
std::cout << std::format("{}", p1);                           //  /usr/bin


auto p2 = std::filesystem::path("multi\nline");
std::cout << std::format("{}", p2);                          // multi
                                                             // line


auto p3 = std::filesystem::path("multi\nline");
std::cout << std::format("{:?}", p3);                        // "multi\nline"        

Thanks to the format string “{:?}” in the last line, the escape sequence “\n” is not interpreted.

std::inplace_vector

std::inplace_vector “is, a dynamically-resizable vector with compile-time fixed capacity and contiguous embedded storage in which the elements are stored within the vector object itself.” (P0843R8)

This container can be used as a drop-in replacement for std::vector. You might ask yourself, when should I use the inplace _vector or vector.

The proposal P0843R8 gives you the answer:

  • memory allocation is not possible, e.g., embedded environments without a free store, where only a stack and the static memory segment are available,
  • memory allocation imposes an unacceptable performance penalty, e.g., with respect to latency,
  • allocation of objects with complex lifetimes in the static-memory segment is required,
  • std::array is not an option, e.g., if non-default constructible objects must be stored,
  • a dynamically-resizable array is required within constexpr functions,
  • the storage location of the inplace_vector elements is required to be within the inplace_vector object itself (e.g. to support memcpy for serialization purposes).

Ranges Improvements

The ranges library will get new functions: std::ranges::generate_random and std::ranges::concat_view.

The call std::ranges::generate_random(fltArray, g, d) uses the generator g and the distribution d to create the random numbers. The call is equivalent to the following loop:

for(auto& el : fltArray)
el = d(e);
        

constexpr?Extensions

Since C++11, the tendency has continued: More and more become constexpr in C++.

  • The algorithm std::stable sort, std::stable partition, and std::inplace_merge are constexpr in C++26. This is also true for their counterparts in the ranges library.
  • The proposal P1383R2amounts to a (further) liberal sprinkling of constexpr in <cmath> , together with a smattering in <complex>“.

What’s next?

In my next post, I will continue my journey through the library in C++26l

Pramod Kumar Kar

Senior Software Engineer @ Schneider Electric. [C++14/17][Embedded C++] [Embedded Linux] [[Automotive][Health care]

1 个月

Very Nice

要查看或添加评论,请登录