timeline

C++17 – What’s New in the Library?

What’s new in the library? A lot. To make the long story short. We get a std::string_view, parallel algorithm of the Standard Template Library, a file system library, and the three new data types std::any, std::optional, and std::variant. Let’s look at the details.

 

timeline

Our journey starts with std::string_view.

std::string_view

A std::string_view is a non-owning reference to a string. It represents a view of a sequence of characters. This sequence of characters can be a C++ string or a C-string. In a typical way, C++17 offers four type synonyms for the underlying character types.

std::string_view      std::basic_string_view<char>
std::wstring_view     std::basic_string_view<wchar_t>
std::u16string_view   std::basic_string_view<char16_t>
std::u32string_view   std::basic_string_view<char32_t>

The question remains. Why do we need a std::string_view? Why had Google, LLVM, and Bloomberg already an implementation of a string view? The answer is easy. It’s pretty cheap to copy a std::string_view. A std::string_view only needs two pieces of information: the pointer to the character sequence and their length. As you may assume, the std::string_view and its three siblings consist mainly of reading operations that follow the interface of std::string. Mainly because it gets the new methods remove_prefix and remove_suffix.

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

Be part of my mentoring programs:

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (starts March 2024)
  • Do you want to stay informed: Subscribe.

     

     

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // string_view.cpp
    
    #include <iostream>
    #include <string>
    #include <experimental/string_view>
    
    int main(){
        
      std::string str = "   A lot of space";
      std::experimental::string_view strView = str;
      strView.remove_prefix(std::min(strView.find_first_not_of(" "), strView.size()));
      std::cout << "str      :  " << str << std::endl 
                << "strView  : " << strView << std::endl;
                     
      std::cout << std::endl;
    
      char arr[] = {'A',' ','l','o','t',' ','o','f',' ','s','p','a','c','e','\0', '\0', '\0'};
      std::experimental::string_view strView2(arr, sizeof arr);
      auto trimPos = strView2.find('\0');
      if(trimPos != strView2.npos) strView2.remove_suffix(strView2.size() - trimPos);
      std::cout << "arr     : " << arr << ", size=" << sizeof arr << std::endl
                << "strView2: " << strView2 << ", size=" << strView2.size() << std::endl;
                  
    }
    

     

    The program should not surprise you. The std::string_view‘s in lines 10 and 18 get their C++-string and character-array reference. In line 11, all leading non-spaces (strView.find_first_not_of(” “)) are removed, and in line 20, all trailing “\0”-characters (strView2.find(‘\0″)) are removed. By using the namespace experimental, I can already execute the program at cppreference.com.

     string view

    Now, to something more familiar.

    Parallel algorithm of the Standard Template Library

    My story is relatively short. 69 Standard Template Library algorithms (STL) algorithms will be available in sequential, parallel, parallel, and vectorized version. Additionally, we get eight new algorithms. Look at the 69 new variants (black) and the 8 (red) new algorithms.

     stl

     

    That was all. I already wrote a post Parallel Algorithm of the Standard Template Library. On the contrary, the filesystem library should be new to you.

    The filesystem library

    The new filesystem library is based on boost::filesystem. Some of its components are optional. That means not all functionality of std::filesytem is available on each implementation of the filesystem library. For example, FAT-32 does not support symbolic links.

    The library uses three concepts file, file name, and path. Files can be directories, hard links, symbolic links, or regular files. Paths can be absolute or relative.

    There is a powerful interface for reading and manipulating the filesystem. Use cppreference.com for the details. Here is a first impression.

     

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    // filesystem.cpp
    
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <experimental/filesystem>
    namespace fs = std::experimental::filesystem;
     
    int main(){
    
        std::cout << "Current path: " << fs::current_path() << std::endl;
    
        std::string dir= "sandbox/a/b";
        fs::create_directories(dir);
    
        std::ofstream("sandbox/file1.txt");
        fs::path symPath= fs::current_path() /=  "sandbox";
        symPath /= "syma";
        fs::create_symlink("a", "symPath");
        
        std::cout << "fs::is_directory(dir): " << fs::is_directory(dir) << std::endl;
        std::cout << "fs::exists(symPath): "  << fs::exists(symPath) << std::endl;
        std::cout << "fs::symlink(symPath): " << fs::is_symlink(symPath) << std::endl;
        
    
        for(auto& p: fs::recursive_directory_iterator("sandbox"))
            std::cout << p << std::endl;
        // fs::remove_all("sandbox");
        
    }
    

     

    fs::current_path() in line 11 returns the current path. You can create a directory hierarchy (line 14) with std::filesystem. Line 18 looks a little bit odd. The /= is overloaded for a path. Therefore, I can directly create a symbolic link in line 19. You can check the properties of a file (lines 21 – 23).   The call recursive_directory_iterator in line 26 is quite powerful. You can use it to traverse directories recursively. Of course, I can not remove a directory (line 28) on an online compiler.

    Here is the output of the program.

    filesystem

    What has the new data type std::any, std::optional, and std::variant in common? They are based on boost.

    std::any

    std::any will be the right choice if you want a container with an arbitrary type. The arbitrary type is not a hundred percent correct. std::any requires, that its values must be copyable. Here is a short example.

     

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // any.cpp
    
    #include <iostream>
    #include <string>
    #include <vector>
    #include <any>
    
    struct MyClass{};
    
    int main(){
        
        std::cout << std::boolalpha;
        
        std::vector<std::any> anyVec(true,2017,std::string("test"),3.14,MyClass());
        std::cout << "std::any_cast<bool>anyVec[0]: " << std::any_cast<bool>(anyVec[0]); // true
        int myInt= std::any_cast<int>(anyVec[1]);                                        
        std::cout << "myInt: " << myInt << std::endl;                                    // 2017
        
        std::cout << std::endl;
        std::cout << "anyVec[0].type().name(): " << anyVec[0].type().name();             // b
        std::cout << "anyVec[1].type().name(): " << anyVec[1].type().name();             // i
        
    }
    

     

    The output of the program is in the source code. Line 14 defines a std::vector<std::any>. To get one of its elements, you have to use std::any_cast. If you use the wrong type, you will get a std::bad_any_cast exception. For further details, go to cppreferenc.com or wait for my additional post.

    std::any can have values of arbitrary types, std::optional can have a value or no value.

    std::optional

    I will make it relatively short. In the post Monads in C++, I already wrote about the monad std::optional.

    The third new data type from boost is std::variant.

    std::variant

    A std::variant is a type-safe union. An instance of std::variant has a value from one of its types. The type must not be a reference, array, or void. A union can have one type more than once. A default-initialized std::variant will be initialized with its first type. In this case, the first type must have a default constructor. Here is an example based on cppreference.com. 

     

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // variant.cpp
    
    #include <variant>
    #include <string>
     
    int main(){
    
      std::variant<int, float> v, w;
      v = 12;                              // v contains int
      int i = std::get<int>(v);
      w = std::get<int>(v);
      w = std::get<0>(v);                  // same effect as the previous line
      w = v;                               // same effect as the previous line
     
      //  std::get<double>(v);             // error: no double in [int, float]
      //  std::get<3>(v);                  // error: valid index values are 0 and 1
     
      try{
        std::get<float>(w);                // w contains int, not float: will throw
      }
      catch (std::bad_variant_access&) {}
     
      std::variant<std::string> v("abc");  // converting constructors work when unambiguous
      v = "def";                           // converting assignment also works when unambiguous
    
    }
    

     

    I define in line 8 both variants v and w. Both can have an int and a float value. Their value is 0. v becomes 12 on line 9. std::get<int>(v) returns the value. In lines 11-13, you see three possibilities to assign variant v the variant w. But you have to keep a few rules in mind. You can ask for the value of a variant by type (line 15) or index (line 16). The type must be unique and the index valid. On line 19, the variant w holds an int value. Therefore, I get a std::bad_variant_access exception in line 21. A conversion can occur if the constructor call or assignment call is unambiguous. That is why it’s possible to construct a std::variant<std::string> in line 23 with a C-string or assign a new C-string to the variant (line 24).

     What’s next?

    I stick with the C++17 standard. After I gave in this and the last post an overview of the core language and the library, I will dive into the next post into the details (Proofreader Marc Bertola).

     

     

     

    Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, Marco Parri Empoli, moon, and Philipp Lenk.

    Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.

    My special thanks to Embarcadero
    My special thanks to PVS-Studio
    My special thanks to Tipi.build 
    My special thanks to Take Up Code
    My special thanks to SHAVEDYAKS

    Seminars

    I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

    Standard Seminars (English/German)

    Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

    • C++ – The Core Language
    • C++ – The Standard Library
    • C++ – Compact
    • C++11 and C++14
    • Concurrency with Modern C++
    • Design Pattern and Architectural Pattern with C++
    • Embedded Programming with Modern C++
    • Generic Programming (Templates) with C++
    • Clean Code with Modern C++
    • C++20

    Online Seminars (German)

    Contact Me

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *