{"id":5232,"date":"2017-03-31T05:48:49","date_gmt":"2017-03-31T05:48:49","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-17-what-s-new-in-the-library\/"},"modified":"2023-06-26T12:18:44","modified_gmt":"2023-06-26T12:18:44","slug":"c-17-what-s-new-in-the-library","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-17-what-s-new-in-the-library\/","title":{"rendered":"C++17 &#8211; What&#8217;s New in the Library?"},"content":{"rendered":"<p>What&#8217;s new in the library? A lot. To make the long story short. We get a<span style=\"font-family: courier new,courier;\"> std::string_view<\/span>, parallel algorithm of the Standard Template Library, a file system library, and the three new data types<span style=\"font-family: courier new,courier;\"> <\/span><span style=\"font-family: courier new,courier;\">std::any<\/span>, <span style=\"font-family: courier new,courier;\">std::optional<\/span>, and <span style=\"font-family: courier new,courier;\">std::variant.<\/span> Let&#8217;s look at the details.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4724\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/04\/timeline.png\" alt=\"timeline\" width=\"700\" height=\"338\" style=\"margin: 15px;\" \/><\/p>\n<p>Our journey starts with <span style=\"font-family: courier new,courier;\">std::string_view<\/span>.<\/p>\n<h2>std::string_view<\/h2>\n<p>A <span style=\"font-family: Courier New,Courier,monospace;\">std::string_view<\/span> 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.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">std::string_view      std::basic_string_view&lt;<span style=\"color: #2b91af;\">char<\/span>&gt;\r\nstd::wstring_view     std::basic_string_view&lt;<span style=\"color: #2b91af;\">wchar_t<\/span>&gt;\r\nstd::u16string_view   std::basic_string_view&lt;<span style=\"color: #2b91af;\">char16_t<\/span>&gt;\r\nstd::u32string_view   std::basic_string_view&lt;<span style=\"color: #2b91af;\">char32_t<\/span>&gt;<br \/>\r\n<\/pre>\n<p>The question remains. Why do we need a <span style=\"font-family: Courier New,Courier,monospace;\">std::string_view?<\/span> Why had Google, LLVM, and Bloomberg already an implementation of a string view? The answer is easy. It&#8217;s pretty cheap to copy a <span style=\"font-family: courier;\">std::string_view<\/span>. A <span style=\"font-family: Courier New,Courier,monospace;\">std::string_view<\/span> only needs two pieces of information: the pointer to the character sequence and their length. As you may assume, the <span style=\"font-family: courier new,courier;\">std::string_view<\/span> and its three siblings consist mainly of reading operations that follow the interface of <span style=\"font-family: courier new,courier;\">std::string<\/span>. Mainly because it gets the new methods<span style=\"font-family: Courier New,Courier,monospace;\"> remove_prefix<\/span> and <span style=\"font-family: Courier New,Courier,monospace;\">remove_suffix<\/span>.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ string_view.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;experimental\/string_view&gt;<\/span>\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n    \r\n  std::string str = <span style=\"color: #a31515;\">\"   A lot of space\"<\/span>;\r\n  std::experimental::string_view strView = str;\r\n  strView.remove_prefix(std::min(strView.find_first_not_of(<span style=\"color: #a31515;\">\" \"<\/span>), strView.size()));\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"str      :  \"<\/span> &lt;&lt; str &lt;&lt; std::endl \r\n            &lt;&lt; <span style=\"color: #a31515;\">\"strView  : \"<\/span> &lt;&lt; strView &lt;&lt; std::endl;\r\n                 \r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  <span style=\"color: #2b91af;\">char<\/span> arr[] = {<span style=\"color: #a31515;\">'A'<\/span>,<span style=\"color: #a31515;\">' '<\/span>,<span style=\"color: #a31515;\">'l'<\/span>,<span style=\"color: #a31515;\">'o'<\/span>,<span style=\"color: #a31515;\">'t'<\/span>,<span style=\"color: #a31515;\">' '<\/span>,<span style=\"color: #a31515;\">'o'<\/span>,<span style=\"color: #a31515;\">'f'<\/span>,<span style=\"color: #a31515;\">' '<\/span>,<span style=\"color: #a31515;\">'s'<\/span>,<span style=\"color: #a31515;\">'p'<\/span>,<span style=\"color: #a31515;\">'a'<\/span>,<span style=\"color: #a31515;\">'c'<\/span>,<span style=\"color: #a31515;\">'e'<\/span>,<span style=\"color: #a31515;\">'\\0'<\/span>, <span style=\"color: #a31515;\">'\\0'<\/span>, <span style=\"color: #a31515;\">'\\0'<\/span>};\r\n  std::experimental::string_view strView2(arr, <span style=\"color: #0000ff;\">sizeof<\/span> arr);\r\n  <span style=\"color: #0000ff;\">auto<\/span> trimPos = strView2.find(<span style=\"color: #a31515;\">'\\0'<\/span>);\r\n  <span style=\"color: #0000ff;\">if<\/span>(trimPos != strView2.npos) strView2.remove_suffix(strView2.size() - trimPos);\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"arr     : \"<\/span> &lt;&lt; arr &lt;&lt; <span style=\"color: #a31515;\">\", size=\"<\/span> &lt;&lt; <span style=\"color: #0000ff;\">sizeof<\/span> arr &lt;&lt; std::endl\r\n            &lt;&lt; <span style=\"color: #a31515;\">\"strView2: \"<\/span> &lt;&lt; strView2 &lt;&lt; <span style=\"color: #a31515;\">\", size=\"<\/span> &lt;&lt; strView2.size() &lt;&lt; std::endl;\r\n              \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The program should not surprise you. The<span style=\"font-family: courier new,courier;\"> std::string_view<\/span>&#8216;s in lines 10 and 18 get their C++-string and character-array reference. In line 11, all leading non-spaces (<span style=\"font-family: courier new,courier;\">strView.find_first_not_of(&#8221; &#8220;)<\/span>) are removed, and in line 20, all trailing &#8220;\\0&#8221;-characters (<span style=\"font-family: courier new,courier;\">strView2.find(&#8216;\\0&#8243;)<\/span>) are removed. By using the namespace <span style=\"font-family: courier new,courier;\">experimental<\/span>, I can already execute the program at <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/string\/basic_string_view\">cppreference.com<\/a>.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5229\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/string_view.png\" alt=\"string view\" style=\"margin: 15px;\" width=\"400\" height=\"166\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/string_view.png 400w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/string_view-300x125.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>Now, to something more familiar.<\/p>\n<\/p>\n<h2>Parallel algorithm of the Standard Template Library<\/h2>\n<p>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.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5230\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/stl.PNG\" alt=\"stl\" width=\"700\" height=\"486\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/stl.PNG 764w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/stl-300x208.png 300w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>That was all. I already wrote a post <a href=\"https:\/\/www.modernescpp.com\/index.php\/parallel-algorithm-of-the-standard-template-library\">Parallel Algorithm of the Standard Template Library<\/a>. On the contrary, the filesystem library should be new to you.<\/p>\n<h2>The filesystem library<\/h2>\n<p>The new filesystem library is based on <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_59_0\/libs\/filesystem\/doc\/reference.html\">boost::filesystem<\/a>. Some of its components are optional. That means not all functionality of <span style=\"font-family: courier new,courier;\">std::filesytem<\/span> is available on each implementation of the filesystem library. For example, FAT-32 does not support symbolic links.<\/p>\n<p>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.<\/p>\n<p>There is a powerful interface for reading and manipulating the filesystem. Use <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/filesystem\">cppreference.com<\/a> for the details. Here is a first impression.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ filesystem.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;fstream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;experimental\/filesystem&gt;<\/span>\r\n<span style=\"color: #0000ff;\">namespace<\/span> fs = std::experimental::filesystem;\r\n \r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Current path: \"<\/span> &lt;&lt; fs::current_path() &lt;&lt; std::endl;\r\n\r\n    std::string dir= <span style=\"color: #a31515;\">\"sandbox\/a\/b\"<\/span>;\r\n    fs::create_directories(dir);\r\n\r\n    std::ofstream(<span style=\"color: #a31515;\">\"sandbox\/file1.txt\"<\/span>);\r\n    fs::path symPath= fs::current_path() \/=  <span style=\"color: #a31515;\">\"sandbox\"<\/span>;\r\n    symPath \/= <span style=\"color: #a31515;\">\"syma\"<\/span>;\r\n    fs::create_symlink(<span style=\"color: #a31515;\">\"a\"<\/span>, <span style=\"color: #a31515;\">\"symPath\"<\/span>);\r\n    \r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"fs::is_directory(dir): \"<\/span> &lt;&lt; fs::is_directory(dir) &lt;&lt; std::endl;\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"fs::exists(symPath): \"<\/span>  &lt;&lt; fs::exists(symPath) &lt;&lt; std::endl;\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"fs::symlink(symPath): \"<\/span> &lt;&lt; fs::is_symlink(symPath) &lt;&lt; std::endl;\r\n    \r\n\r\n    <span style=\"color: #0000ff;\">for<\/span>(<span style=\"color: #0000ff;\">auto<\/span>&amp; p: fs::recursive_directory_iterator(<span style=\"color: #a31515;\">\"sandbox\"<\/span>))\r\n        std::cout &lt;&lt; p &lt;&lt; std::endl;\r\n    <span style=\"color: #008000;\">\/\/ fs::remove_all(\"sandbox\");<\/span>\r\n    \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">fs::current_path()<\/span> in line 11 returns the current path. You can create a directory hierarchy (line 14) with <span style=\"font-family: courier new,courier;\">std::filesystem.<\/span> Line 18 looks a little bit odd. The <span style=\"font-family: courier new,courier;\">\/=<\/span> 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 &#8211; 23).&nbsp;&nbsp; The call <span style=\"font-family: courier new,courier;\">recursive_directory_iterator<\/span> 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.<\/p>\n<p>Here is the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5231\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/filesystem.png\" alt=\"filesystem\" style=\"margin: 15px;\" width=\"407\" height=\"291\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/filesystem.png 407w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/03\/filesystem-300x214.png 300w\" sizes=\"auto, (max-width: 407px) 100vw, 407px\" \/><\/p>\n<p>What has the new data type <span style=\"font-family: courier new,courier;\">std::any, std::optional, <\/span><span>and<\/span><span style=\"font-family: courier new,courier;\"> std::variant <\/span>in common? They are based on <a href=\"http:\/\/www.boost.org\/\">boost.<\/a><\/p>\n<h2>std::any<\/h2>\n<p><span style=\"font-family: courier new,courier;\">std::any<\/span> will be the right choice if you want a container with an arbitrary type. The arbitrary type is not a hundred percent correct. <span style=\"font-family: courier new,courier;\">std::any<\/span> requires, that its values must be copyable. Here is a short example.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ any.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;vector&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;any&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> MyClass{};\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n    \r\n    std::cout &lt;&lt; std::boolalpha;\r\n    \r\n    std::vector&lt;std::any&gt; anyVec(true,2017,std::string(<span style=\"color: #a31515;\">\"test\"<\/span>),3.14,MyClass());\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"std::any_cast&lt;bool&gt;anyVec[0]: \"<\/span> &lt;&lt; std::any_cast&lt;<span style=\"color: #2b91af;\">bool<\/span>&gt;(anyVec[0]); <span style=\"color: #008000;\">\/\/ true<\/span>\r\n    <span style=\"color: #2b91af;\">int<\/span> myInt= std::any_cast&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(anyVec[1]);                                        \r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"myInt: \"<\/span> &lt;&lt; myInt &lt;&lt; std::endl;                                    <span style=\"color: #008000;\">\/\/ 2017<\/span>\r\n    \r\n    std::cout &lt;&lt; std::endl;\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"anyVec[0].type().name(): \"<\/span> &lt;&lt; anyVec[0].type().name();             <span style=\"color: #008000;\">\/\/ b<\/span>\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"anyVec[1].type().name(): \"<\/span> &lt;&lt; anyVec[1].type().name();             <span style=\"color: #008000;\">\/\/ i<\/span>\r\n    \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The output of the program is in the source code. Line 14 defines a <span style=\"font-family: courier new,courier;\">std::vector&lt;std::any&gt;<\/span>. To get one of its elements, you have to use <span style=\"font-family: courier new,courier;\">std::any_cast<\/span>. If you use the wrong type, you will get a <span style=\"font-family: courier new,courier;\">std::bad_any_cast<\/span> exception. For further details, go to <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/any\">cppreferenc.com <\/a>or wait for my additional post.<\/p>\n<p><span style=\"font-family: courier new,courier;\">std::any<\/span> can have values of arbitrary types, <span style=\"font-family: courier new,courier;\">std::optional<\/span> can have a value or no value.<\/p>\n<h2>std::optional<\/h2>\n<p>I will make it relatively short. In the post <a href=\"https:\/\/www.modernescpp.com\/index.php\/monads-in-c\">Monads in C++<\/a>, I already wrote about the monad <span style=\"font-family: courier new,courier;\">std::optional. <\/span><\/p>\n<p>The third new data type from boost is <span style=\"font-family: courier new,courier;\">std::variant.<\/span><\/p>\n<h2>std::variant<\/h2>\n<p>A <span style=\"font-family: courier new,courier;\">std::variant<\/span> is a type-safe union. An instance of <span style=\"font-family: courier new,courier;\">std::variant<\/span> has a value from one of its types. The type must not be a reference, array, or <span style=\"font-family: courier new,courier;\">void.<\/span> A union can have one type more than once. A default-initialized <span style=\"font-family: courier new,courier;\">std::variant<\/span> will be initialized with its first type. In this case, the first type must have a default constructor. Here is an example based on <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/variant\">cppreference.com.<\/a>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ variant.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;variant&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;string&gt;<\/span>\r\n \r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::variant&lt;<span style=\"color: #2b91af;\">int<\/span>, <span style=\"color: #2b91af;\">float<\/span>&gt; v, w;\r\n  v = 12;                              <span style=\"color: #008000;\">\/\/ v contains int<\/span>\r\n  <span style=\"color: #2b91af;\">int<\/span> i = std::get&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(v);\r\n  w = std::get&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(v);\r\n  w = std::get&lt;0&gt;(v);                  <span style=\"color: #008000;\">\/\/ same effect as the previous line<\/span>\r\n  w = v;                               <span style=\"color: #008000;\">\/\/ same effect as the previous line<\/span>\r\n \r\n  <span style=\"color: #008000;\">\/\/  std::get&lt;double&gt;(v);             \/\/ error: no double in [int, float]<\/span>\r\n  <span style=\"color: #008000;\">\/\/  std::get&lt;3&gt;(v);                  \/\/ error: valid index values are 0 and 1<\/span>\r\n \r\n  try{\r\n    std::get&lt;<span style=\"color: #2b91af;\">float<\/span>&gt;(w);                <span style=\"color: #008000;\">\/\/ w contains int, not float: will throw<\/span>\r\n  }\r\n  <span style=\"color: #0000ff;\">catch<\/span> (std::bad_variant_access&amp;) {}\r\n \r\n  std::variant&lt;std::string&gt; v(<span style=\"color: #a31515;\">\"abc\"<\/span>);  <span style=\"color: #008000;\">\/\/ converting constructors work when unambiguous<\/span>\r\n  v = <span style=\"color: #a31515;\">\"def\"<\/span>;                           <span style=\"color: #008000;\">\/\/ converting assignment also works when unambiguous<\/span>\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I define in line 8 both variants <span style=\"font-family: courier new,courier;\">v<\/span> and<span style=\"font-family: courier new,courier;\"> w<\/span>. Both can have an <span style=\"font-family: courier new,courier;\">int<\/span> and a <span style=\"font-family: courier new,courier;\">float<\/span> value. Their value is 0. <span style=\"font-family: courier new,courier;\">v<\/span> becomes 12 on line 9. <span style=\"font-family: courier new,courier;\">std::get&lt;int&gt;(v)<\/span> returns the value. In lines 11-13, you see three possibilities to assign variant <span style=\"font-family: courier new,courier;\">v<\/span> the variant <span style=\"font-family: courier new,courier;\">w.<\/span> 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 <span style=\"font-family: courier new,courier;\">w<\/span> holds an <span style=\"font-family: courier new,courier;\">int<\/span> value. Therefore, I get a <span style=\"font-family: courier new,courier;\">std::bad_variant_access<\/span> exception in line 21. A conversion can occur if the constructor call or assignment call is unambiguous. That is why it&#8217;s possible to construct a <span style=\"font-family: courier new,courier;\">std::variant&lt;std::string&gt;<\/span> in line 23 with a C-string or assign a new C-string to the variant (line 24).<\/p>\n<h2>&nbsp;What&#8217;s next?<\/h2>\n<p>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 <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-17-more-details-to-the-core-language\">next post<\/a> into the details (<strong>Proofreader Marc Bertola<\/strong>).<\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What&#8217;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&#8217;s look at the details.<\/p>\n","protected":false},"author":21,"featured_media":4724,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[370],"tags":[463],"class_list":["post-5232","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-17","tag-string"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5232","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5232"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5232\/revisions"}],"predecessor-version":[{"id":6876,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5232\/revisions\/6876"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4724"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5232"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5232"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5232"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}