{"id":5287,"date":"2017-07-21T18:46:42","date_gmt":"2017-07-21T18:46:42","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guideline-the-guidelines-support-library\/"},"modified":"2023-06-26T12:09:58","modified_gmt":"2023-06-26T12:09:58","slug":"c-core-guideline-the-guidelines-support-library","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guideline-the-guidelines-support-library\/","title":{"rendered":"C++ Core Guideline: The Guideline Support Library"},"content":{"rendered":"<p>The guidelines support library (GSL) is a small library for supporting the guidelines of the C++ core guidelines. It should help to write better C++ programs. Therefore, its key concerns are memory safety and type safety. They are already a few implementations of the GSL available.<\/p>\n<p><!--more--><\/p>\n<p>The GSL is a header-only library. Hence, you can use the functions and types of the library quite easily. The best-known implementation is the one from Microsoft, hosted at GitHub: <a href=\"https:\/\/github.com\/Microsoft\/GSL\">Microsoft\/GSL<\/a>. The Microsoft version requires C++14 support and runs on various platforms. Here are the leading platforms.<\/p>\n<ul>\n<li>Windows using Visual Studio 2015<\/li>\n<li>Windows using Visual Studio 2017<\/li>\n<li>GNU\/Linux using Clang\/LLVM 3.6<\/li>\n<li>GNU\/Linux using GCC 5.1<\/li>\n<\/ul>\n<p>But that is not all; there exist more implementations on GitHub. I want explicitly emphasize the <a href=\"https:\/\/github.com\/martinmoene\/gsl-lite\">GSL-lite <\/a>implementation of Martin Moene. His implementation even works with C++98 and C++03.<\/p>\n<p>Before I dive into the details, there is one issue that makes my writing difficult: the lack of good documentation or tutorials. To get an idea, of what the function and types should support, you have to install the library and analyze the unit test. That is not the kind of documentation I expect. In contrast, installing and using Microsoft&#8217;s implementation of the GSL was relatively easy on Windows and Linux.<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" alignright size-full wp-image-5286\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/07\/support.png\" alt=\"support\" width=\"400\" height=\"400\" style=\"margin: 15px; float: right;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/07\/support.png 640w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/07\/support-300x300.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/07\/support-150x150.png 150w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>So, let me dive into the details. The GSL consists of five components. Here is a first overview:<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-views\">GSL.view: Views<\/a>\n<ul>\n<li><span style=\"font-family: courier new,courier;\">span&lt;T&gt;<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">string_span&lt;T&gt;<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">(cw)zstring<\/span><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-ownership\">GSL.owner<\/a>\n<ul>\n<li><span style=\"font-family: courier new,courier;\">owner&lt;T&gt;<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">unique_ptr&lt;T&gt;<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">shared_ptr&lt;T&gt;<\/span><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-assertions\">GSL.assert: Assertions<\/a>\n<ul>\n<li><span style=\"font-family: courier new,courier;\">Expects()<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">Ensures()<\/span><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-utilities\">GSL.util: Utilities<\/a>\n<ul>\n<li><span style=\"font-family: courier new,courier;\">narrow<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">narrow_cast()<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">not_null&lt;T&gt;<\/span><\/li>\n<li><span style=\"font-family: courier new,courier;\">finally<\/span><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-gsl-concepts\">GSL.concept: Concepts<\/a>\n<ul>\n<li><code class=\"highlighter-rouge no-highlight\">Range<\/code><\/li>\n<li><code class=\"highlighter-rouge no-highlight\">String<\/code><\/li>\n<li><code class=\"highlighter-rouge no-highlight\">Number<\/code><\/li>\n<li><code class=\"highlighter-rouge no-highlight\">Sortable<\/code><\/li>\n<li><code class=\"highlighter-rouge no-highlight\">Pointer<\/code><\/li>\n<li>&#8230;<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/li>\n<\/ul>\n<p>You may wonder why the GSL has its own smart pointer <span style=\"font-family: courier new,courier;\">gsl::unique_ptr<\/span> and <span style=\"font-family: courier new,courier;\">gsl::shared_ptr<\/span> because the C++11 standard has <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span> and <span style=\"font-family: courier new,courier;\">std::shared_ptr.<\/span> The idea is simple: you can use the GSL with a compiler that does not support C++11. Many functions and types the GSL support may become part of C++20. That holds, at least for the concepts and the assertions. It is also probable that the remaining parts will become part of upcoming C++ standards.<\/p>\n<\/p>\n<h2>The components<\/h2>\n<p>Let&#8217;s have a look at the Views,<\/p>\n<h3>GSL.view: Views<\/h3>\n<p>A view is never an owner. In the case of a <span style=\"font-family: courier new,courier;\">gsl::span&lt;T&gt;<\/span>, it represents a non-owning range of contiguous memory. This can be an array, a pointer with a size, or a <span style=\"font-family: courier new,courier;\">std::vector<\/span>. The same holds for <span style=\"font-family: courier new,courier;\">gsl::string_span&lt;T&gt;<\/span> or a zero-terminated C strings:<span style=\"font-family: courier new,courier;\"> gsl::(cw)string.<\/span> The main reason for having a <span style=\"font-family: courier new,courier;\">gsl::span&lt;T&gt;<\/span> is that a plain array will be decayed to a pointer if passed to a function; therefore, the size is lost.<\/p>\n<p><strong><span style=\"font-family: courier new,courier;\">gsl::span&lt;T&gt;<\/span><\/strong> automatically deduces the size of the plain array or the <span style=\"font-family: courier new,courier;\">std::vector.<\/span> If you use a pointer, you have to provide the size.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> copy_n(<span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">*<\/span> p, T<span style=\"color: #555555;\">*<\/span> q, <span style=\"color: #007788; font-weight: bold;\">int<\/span> n){}\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> copy(gsl<span style=\"color: #555555;\">::<\/span>span<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> T<span style=\"color: #555555;\">&gt;<\/span> src, gsl<span style=\"color: #555555;\">::<\/span>span<span style=\"color: #555555;\">&lt;<\/span>T<span style=\"color: #555555;\">&gt;<\/span> des){}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main(){\r\n    \r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> arr1[] <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>};\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> arr2[] <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>};\r\n  \r\n  copy_n(arr1, arr2, <span style=\"color: #ff6600;\">3<\/span>);         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n  copy(arr1, arr2);              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In contrast to the function<span style=\"font-family: courier new,courier;\"> copy_n<\/span> (1), you have not provided the number of elements for the function <span style=\"font-family: courier new,courier;\">copy<\/span> (2). Hence, a common cause of errors is gone with <span style=\"font-family: courier new,courier;\">gsl::span&lt;T&gt;<\/span>.<\/p>\n<p>There are various kinds of owners in the GSL.<\/p>\n<h3 id=\"gslowner-ownership-pointers\">GSL.owner: Ownership pointers<\/h3>\n<p>I assume you know <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span> and <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span>; therefore, you know <span style=\"font-family: courier new,courier;\">gsl::unique_ptr<\/span> and <span style=\"font-family: courier new,courier;\">gsl::shared_ptr<\/span>. If not, here are my posts about <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/smart-pointers\">smart pointers<\/a>.<\/p>\n<p><strong><span style=\"font-family: courier new,courier;\">gsl::owner&lt;T*&gt;<\/span><\/strong> marks a pointer that owns the referenced object. You should use <span style=\"font-family: courier new,courier;\">gsl::owner&lt;T&gt;<\/span> if you can not use resource handles such as smart pointers or containers. The critical point about the owner is that you must explicitly free the resource. Raw pointers not marked as gsl::owner&lt;T*&gt; are considered non-owning in the C++ core guidelines. Therefore, you do not have to free the resource.<\/p>\n<p><span style=\"font-family: courier new,courier;\">gsl::dyn_array&lt;T<\/span>&gt; and <span style=\"font-family: courier new,courier;\">gsl::stack_array&lt;T&gt;<\/span> are two new array types.<\/p>\n<ul>\n<li><strong><span style=\"font-family: courier new,courier;\">gsl::dyn_array&lt;T&gt;<\/span><\/strong> is a heap-allocated array with a fixed size of elements specified at run-time.<\/li>\n<li><strong><span style=\"font-family: courier new,courier;\">gsl::stack_array&lt;T&gt; <\/span><\/strong>is<span style=\"font-family: courier new,courier;\"> a <\/span>stack-allocated array with a fixed size of elements specified at run-time.<\/li>\n<\/ul>\n<h3 id=\"gslassert-assertions\">GSL.assert: Assertions<\/h3>\n<p>Thanks to <strong><span style=\"font-family: courier new,courier;\">Expects()<\/span><\/strong> and <span style=\"font-family: courier new,courier;\"><strong>Ensures()<\/strong>,<\/span> you can state preconditions and postconditions for your functions. You have to place them in the function body, but this will later be moved to the function declaration. Both functions are part of the <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0380r1.pdf\">contract proposal<\/a>.<\/p>\n<p>Here is a simple example using <span style=\"font-family: courier new,courier;\">Expects()<\/span> and <span style=\"font-family: courier new,courier;\">Ensures().<\/span><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">area<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> height, <span style=\"color: #007788; font-weight: bold;\">int<\/span> width)\r\n{\r\n    Expects(height <span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #ff6600;\">0<\/span>);            \r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res <span style=\"color: #555555;\">=<\/span> height <span style=\"color: #555555;\">*<\/span> width;\r\n    Ensures(res <span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #ff6600;\">0<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> res;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h3 id=\"gslutil-utilities\">GSL.util: Utilities<\/h3>\n<p><span style=\"font-family: courier new,courier;\">gsl::narrow_cast&lt;T&gt;<\/span> and <span style=\"font-family: courier new,courier;\">gsl::narrow<\/span> are two new casts.<\/p>\n<ul>\n<li><strong><span style=\"font-family: courier new,courier;\">gsl::narrow_cast&lt;T&gt;<\/span><\/strong> is a <span style=\"font-family: courier new,courier;\">static_cast&lt;T&gt;<\/span> that only expresses its intent. A narrowing conversion may happen.<\/li>\n<li><strong><span style=\"font-family: courier new,courier;\">gsl::narrow<\/span><\/strong> is a <span style=\"font-family: courier new,courier;\">static_cast&lt;T&gt;<\/span> that throws a<span style=\"font-family: courier new,courier;\"> narrowing_error<\/span> exception if <code class=\"highlighter-rouge no-highlight\">static_cast&lt;T&gt;(x) != x<\/code><code>. <\/code><code class=\"highlighter-rouge no-highlight\"><\/code><\/li>\n<\/ul>\n<p><strong><span style=\"font-family: courier new,courier;\">gsl::not_null&lt;T*&gt;<\/span><\/strong> models a pointer that never should be a <span style=\"font-family: courier new,courier;\">nullptr.<\/span> You will get a compiler error if you set a <span style=\"font-family: courier new, courier;\">gsl::not_null&lt;T*&gt;<\/span> pointer to a nullptr. You can even put a smart pointer such as <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span> or <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> into a <span style=\"font-family: courier new,courier;\">gsl::not_null&lt;T*&gt;. <\/span>Typically, you use<span style=\"font-family: courier new,courier;\"> gsl::not_null&lt;T*&gt;<\/span> for function parameters and their return type. Therefore, you can not forget to check if a pointer holds a value.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">getLength<\/span>(gsl<span style=\"color: #555555;\">::<\/span>not_null<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*&gt;<\/span> p); <span style=\"color: #0099ff; font-style: italic;\">\/\/ p cannot be a nullptr<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">getLength<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> p);                <span style=\"color: #0099ff; font-style: italic;\">\/\/ p can be a nullptr<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Both functions state their intent explicitly. The second one can accept a <span style=\"font-family: courier new,courier;\">nullptr.<\/span><\/p>\n<p><strong><span style=\"font-family: courier new,courier;\">finally<\/span><\/strong> allows you to register a callable that will run at the end of the scope.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">f<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n)\r\n{\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span><span style=\"color: #555555;\">*<\/span> p <span style=\"color: #555555;\">=<\/span> malloc(<span style=\"color: #ff6600;\">1<\/span>, n);\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> _ <span style=\"color: #555555;\">=<\/span> finally([p] { free(p); });\r\n    ...\r\n}\r\n    \r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>At the end of the function <span style=\"font-family: courier new,courier;\">f,<\/span> the lambda function <span style=\"font-family: courier new,courier;\">[p] { free(p); }<\/span> will be invoked automatically.<\/p>\n<p>According to the C++ core guidelines, you should consider <span style=\"font-family: courier new,courier;\">finally<\/span> as a last resort if you can not use proper resource management such as smart pointers or STL containers. <code class=\"highlighter-rouge no-highlight\"><\/code><\/p>\n<h3 id=\"gslconcept-concepts\">GSL.concept: Concepts<\/h3>\n<p>I make it short because most concepts are defined in the <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/n4569.pdf\">Ranges TS<\/a>.&nbsp; Here are my posts on <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/concepts\">concepts<\/a>.<\/p>\n<h2>My last words<\/h2>\n<p>I&#8217;m impressed by the guideline support library. What I like, in particular, is that it requires no C++11 conformant compiler. You can even use it in legacy code, making it a lot more memory- and type-safe.&nbsp; I forgot that the GSL &#8220;<strong>aim for zero-overhead when compared to equivalent hand-written checks.&#8221;. <\/strong>That&#8217;s a promise.<strong><br \/><\/strong><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>After my short detour to the GSL I will return to the rules of the C++ core guidelines. The <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-functions\">next post<\/a> is about functions in general, the parameters of functions, and their return value in particular.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The guidelines support library (GSL) is a small library for supporting the guidelines of the C++ core guidelines. It should help to write better C++ programs. Therefore, its key concerns are memory safety and type safety. They are already a few implementations of the GSL available.<\/p>\n","protected":false},"author":21,"featured_media":5286,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[465],"class_list":["post-5287","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-gsl"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5287","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=5287"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5287\/revisions"}],"predecessor-version":[{"id":6868,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5287\/revisions\/6868"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5286"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}