aboutsummaryrefslogblamecommitdiffhomepage
path: root/development/c++.html
blob: c2d418bbe0595f502ee6b57d633a483377a16175 (plain) (tree)
1
2
3
4
5
6
7
8
9
               
                                        



                                            

 
                                 
        

                                                                            
                                                   
 
                                               




                                                                     
 
                      
                                                                          
                                                         
 
                                         


                                                            

                                         
 
           
                                        
                             
                                                
                
                                     
                                                                                                             


                                                                                       
                














                                                                                                 
                



                                                                                 
                                          
                                      


                                                      

                 

                                                                         
                                                             
                
                                                      
                               
                                                                                  


                                                                                      

                                   
             


                                                           


                                                                         
                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                  


                                                                          

              





















                                                                                                               


                                                    
                                                                           
                                                           
                                              
                                                                                                                                                                                                  
                                                      
                                



                                                                                                                                                                                                         
                                                                                                                


















                                                                                                                                                                                                                       
 


                          

                                                                       
                                                                                                                                                                                            






                                                                                          
 
                                                                                                                   
                        








                                                                                                                   
                                                                           
                                                                                                  
                                                                                                                                           
                                                                                        





                                                                       
























































































































































































                                                                                                                                                                   


                                                                                                                                                                                                                           

                                                 












                                                                             

                                                  
















                                                                             
             



































































                                                                                                                                                                                                                             
                                                                                                                                                                           




























                                                                                                                                                                                                                                                         



















































                                                                                                                                 


                                               









                                                              


                                                     







                                                              


                                                           









                                       
             
























                                                                                                                                                                          


                                                       















































































                                                                                                                  

















                                                                                                                         
 
















                                                                                                                                
                                                                                                                        





















                                                                                            



                                                            

                                     
                                       
                          


































                                                                                                         
             


                                                                                                    










































































                                                                                                                                                                                                                        






















































                                                                                                                             




                                                                               

























                                                                                 




                                                                          
                                                                                                                                                                                                  

                                                                
 
                                                                                                                                                                                              

                                                                 
 





                                                                       
                                                                                                                                                                                   

                                                        
 
                                                                                                                                                                               

                                                         



                  



                
                                              
                 








                                                     

                                  

 
          

           
<!DOCTYPE HTML>
<html lang="en" class="light" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>c++ - Notes</title>


        <!-- Custom HTML head -->
        
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="../favicon.svg">
        <link rel="shortcut icon" href="../favicon.png">
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        <link rel="stylesheet" href="../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../highlight.css">
        <link rel="stylesheet" href="../tomorrow-night.css">
        <link rel="stylesheet" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->

    </head>
    <body class="sidebar-visible no-js">
    <div id="body-container">
        <!-- Provide site root to javascript -->
        <script>
            var path_to_root = "../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('light')
            html.classList.add(theme);
            var body = document.querySelector('body');
            body.classList.remove('no-js')
            body.classList.add('js');
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            var body = document.querySelector('body');
            var sidebar = null;
            var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            body.classList.remove('sidebar-visible');
            body.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="../intro.html">Introduction</a></li><li class="chapter-item expanded "><a href="../tools/index.html"><strong aria-hidden="true">1.</strong> Tools</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../tools/zsh.html"><strong aria-hidden="true">1.1.</strong> zsh</a></li><li class="chapter-item expanded "><a href="../tools/bash.html"><strong aria-hidden="true">1.2.</strong> bash</a></li><li class="chapter-item expanded "><a href="../tools/fish.html"><strong aria-hidden="true">1.3.</strong> fish</a></li><li class="chapter-item expanded "><a href="../tools/tmux.html"><strong aria-hidden="true">1.4.</strong> tmux</a></li><li class="chapter-item expanded "><a href="../tools/git.html"><strong aria-hidden="true">1.5.</strong> git</a></li><li class="chapter-item expanded "><a href="../tools/awk.html"><strong aria-hidden="true">1.6.</strong> awk</a></li><li class="chapter-item expanded "><a href="../tools/emacs.html"><strong aria-hidden="true">1.7.</strong> emacs</a></li><li class="chapter-item expanded "><a href="../tools/gpg.html"><strong aria-hidden="true">1.8.</strong> gpg</a></li><li class="chapter-item expanded "><a href="../tools/gdb.html"><strong aria-hidden="true">1.9.</strong> gdb</a></li><li class="chapter-item expanded "><a href="../tools/gdbserver.html"><strong aria-hidden="true">1.10.</strong> gdbserver</a></li><li class="chapter-item expanded "><a href="../tools/radare2.html"><strong aria-hidden="true">1.11.</strong> radare2</a></li><li class="chapter-item expanded "><a href="../tools/qemu.html"><strong aria-hidden="true">1.12.</strong> qemu</a></li><li class="chapter-item expanded "><a href="../tools/pacman.html"><strong aria-hidden="true">1.13.</strong> pacman</a></li><li class="chapter-item expanded "><a href="../tools/dot.html"><strong aria-hidden="true">1.14.</strong> dot</a></li></ol></li><li class="chapter-item expanded "><a href="../monitor/index.html"><strong aria-hidden="true">2.</strong> Resource analysis & monitor</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../monitor/lsof.html"><strong aria-hidden="true">2.1.</strong> lsof</a></li><li class="chapter-item expanded "><a href="../monitor/ss.html"><strong aria-hidden="true">2.2.</strong> ss</a></li><li class="chapter-item expanded "><a href="../monitor/pidstat.html"><strong aria-hidden="true">2.3.</strong> pidstat</a></li><li class="chapter-item expanded "><a href="../monitor/pgrep.html"><strong aria-hidden="true">2.4.</strong> pgrep</a></li><li class="chapter-item expanded "><a href="../monitor/pmap.html"><strong aria-hidden="true">2.5.</strong> pmap</a></li><li class="chapter-item expanded "><a href="../monitor/pstack.html"><strong aria-hidden="true">2.6.</strong> pstack</a></li></ol></li><li class="chapter-item expanded "><a href="../trace_profile/index.html"><strong aria-hidden="true">3.</strong> Trace and Profile</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../trace_profile/strace.html"><strong aria-hidden="true">3.1.</strong> strace</a></li><li class="chapter-item expanded "><a href="../trace_profile/ltrace.html"><strong aria-hidden="true">3.2.</strong> ltrace</a></li><li class="chapter-item expanded "><a href="../trace_profile/perf.html"><strong aria-hidden="true">3.3.</strong> perf</a></li><li class="chapter-item expanded "><a href="../trace_profile/oprofile.html"><strong aria-hidden="true">3.4.</strong> OProfile</a></li><li class="chapter-item expanded "><a href="../trace_profile/time.html"><strong aria-hidden="true">3.5.</strong> time</a></li></ol></li><li class="chapter-item expanded "><a href="../binary/index.html"><strong aria-hidden="true">4.</strong> Binary</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../binary/od.html"><strong aria-hidden="true">4.1.</strong> od</a></li><li class="chapter-item expanded "><a href="../binary/xxd.html"><strong aria-hidden="true">4.2.</strong> xxd</a></li><li class="chapter-item expanded "><a href="../binary/readelf.html"><strong aria-hidden="true">4.3.</strong> readelf</a></li><li class="chapter-item expanded "><a href="../binary/objdump.html"><strong aria-hidden="true">4.4.</strong> objdump</a></li><li class="chapter-item expanded "><a href="../binary/nm.html"><strong aria-hidden="true">4.5.</strong> nm</a></li></ol></li><li class="chapter-item expanded "><a href="../development/index.html"><strong aria-hidden="true">5.</strong> Development</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../development/c++filt.html"><strong aria-hidden="true">5.1.</strong> c++filt</a></li><li class="chapter-item expanded "><a href="../development/c++.html" class="active"><strong aria-hidden="true">5.2.</strong> c++</a></li><li class="chapter-item expanded "><a href="../development/glibc.html"><strong aria-hidden="true">5.3.</strong> glibc</a></li><li class="chapter-item expanded "><a href="../development/gcc.html"><strong aria-hidden="true">5.4.</strong> gcc</a></li><li class="chapter-item expanded "><a href="../development/cmake.html"><strong aria-hidden="true">5.5.</strong> cmake</a></li><li class="chapter-item expanded "><a href="../development/make.html"><strong aria-hidden="true">5.6.</strong> make</a></li><li class="chapter-item expanded "><a href="../development/ld.so.html"><strong aria-hidden="true">5.7.</strong> ld.so</a></li><li class="chapter-item expanded "><a href="../development/symbolver.html"><strong aria-hidden="true">5.8.</strong> symbol versioning</a></li><li class="chapter-item expanded "><a href="../development/python.html"><strong aria-hidden="true">5.9.</strong> python</a></li><li class="chapter-item expanded "><a href="../development/gcov.html"><strong aria-hidden="true">5.10.</strong> gcov</a></li><li class="chapter-item expanded "><a href="../development/pgo.html"><strong aria-hidden="true">5.11.</strong> pgo</a></li></ol></li><li class="chapter-item expanded "><a href="../linux/index.html"><strong aria-hidden="true">6.</strong> Linux</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../linux/systemd.html"><strong aria-hidden="true">6.1.</strong> systemd</a></li><li class="chapter-item expanded "><a href="../linux/coredump.html"><strong aria-hidden="true">6.2.</strong> coredump</a></li><li class="chapter-item expanded "><a href="../linux/ptrace_scope.html"><strong aria-hidden="true">6.3.</strong> ptrace_scope</a></li><li class="chapter-item expanded "><a href="../linux/cryptsetup.html"><strong aria-hidden="true">6.4.</strong> cryptsetup</a></li><li class="chapter-item expanded "><a href="../linux/swap.html"><strong aria-hidden="true">6.5.</strong> swap</a></li><li class="chapter-item expanded "><a href="../linux/input.html"><strong aria-hidden="true">6.6.</strong> input</a></li><li class="chapter-item expanded "><a href="../linux/acl.html"><strong aria-hidden="true">6.7.</strong> acl</a></li><li class="chapter-item expanded "><a href="../linux/zfs.html"><strong aria-hidden="true">6.8.</strong> zfs</a></li></ol></li><li class="chapter-item expanded "><a href="../network/index.html"><strong aria-hidden="true">7.</strong> Network</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../network/tcpdump.html"><strong aria-hidden="true">7.1.</strong> tcpdump</a></li><li class="chapter-item expanded "><a href="../network/firewall-cmd.html"><strong aria-hidden="true">7.2.</strong> firewall-cmd</a></li><li class="chapter-item expanded "><a href="../network/nftables.html"><strong aria-hidden="true">7.3.</strong> nftables</a></li></ol></li><li class="chapter-item expanded "><a href="../web/index.html"><strong aria-hidden="true">8.</strong> Web</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../web/html.html"><strong aria-hidden="true">8.1.</strong> html</a></li><li class="chapter-item expanded "><a href="../web/css.html"><strong aria-hidden="true">8.2.</strong> css</a></li><li class="chapter-item expanded "><a href="../web/chartjs.html"><strong aria-hidden="true">8.3.</strong> chartjs</a></li></ol></li><li class="chapter-item expanded "><a href="../arch/index.html"><strong aria-hidden="true">9.</strong> Arch</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../arch/x86_64.html"><strong aria-hidden="true">9.1.</strong> x86_64</a></li><li class="chapter-item expanded "><a href="../arch/arm64.html"><strong aria-hidden="true">9.2.</strong> arm64</a></li><li class="chapter-item expanded "><a href="../arch/armv7.html"><strong aria-hidden="true">9.3.</strong> armv7</a></li><li class="chapter-item expanded "><a href="../arch/riscv.html"><strong aria-hidden="true">9.4.</strong> riscv</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle">
                <div class="sidebar-resize-indicator"></div>
            </div>
        </nav>

        <!-- Track and set sidebar scroll position -->
        <script>
            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
            sidebarScrollbox.addEventListener('click', function(e) {
                if (e.target.tagName === 'A') {
                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
                }
            }, { passive: true });
            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
            sessionStorage.removeItem('sidebar-scroll');
            if (sidebarScrollTop) {
                // preserve sidebar scroll position when navigating via links within sidebar
                sidebarScrollbox.scrollTop = sidebarScrollTop;
            } else {
                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
                var activeSection = document.querySelector('#sidebar .active');
                if (activeSection) {
                    activeSection.scrollIntoView({ block: 'center' });
                }
            }
        </script>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Notes</h1>

                    <div class="right-buttons">
                        <a href="../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                        <a href="https://github.com/johannst/notes" title="Git repository" aria-label="Git repository">
                            <i id="git-repository-button" class="fa fa-github"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="c"><a class="header" href="#c">c++</a></h1>
<p>openstd <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/standards">cpp standards</a>.</p>
<p>Source files of most examples is available <a href="https://github.com/johannst/notes/tree/master/src/development/c%2B%2B">here</a>.</p>
<h2 id="type-deduction"><a class="header" href="#type-deduction">Type deduction</a></h2>
<p>Force compile error to see what <code>auto</code> is deduced to.</p>
<pre><code class="language-cpp">auto foo = bar();

// force compile error
typename decltype(foo)::_;
</code></pre>
<h2 id="strict-aliasing-and-type-punning"><a class="header" href="#strict-aliasing-and-type-punning">Strict aliasing and type punning</a></h2>
<p>The <code>strict aliasing</code> rules describe via which <code>alias</code> a value can be accessed.</p>
<blockquote>
<p>Informal: an <code>alias</code> is a reference / pointer to a value.</p>
</blockquote>
<p>Accessing a value through an alias that violates the strict aliasing rules is
<code>undefined behavior (UB)</code>.</p>
<p>Examples below on <a href="https://godbolt.org/z/TsvTY9zfj">godbolt</a>.</p>
<pre><code class="language-cpp">int i = 0;

// Valid aliasing (signed / unsigned type).
*reinterpret_cast&lt;signed int*&gt;(&amp;i);
*reinterpret_cast&lt;unsigned int*&gt;(&amp;i);

// Valid aliasing (cv qualified type).
*reinterpret_cast&lt;const int*&gt;(&amp;i);
*reinterpret_cast&lt;const unsigned*&gt;(&amp;i);

// Valid aliasing (byte type).
*reinterpret_cast&lt;char*&gt;(&amp;i);
*reinterpret_cast&lt;std::byte*&gt;(&amp;i);

// Invalid aliasing, dereferencing pointer is UB.
*reinterpret_cast&lt;short*&gt;(&amp;i);
*reinterpret_cast&lt;float*&gt;(&amp;i);
</code></pre>
<blockquote>
<p>NOTE: Casting pointer to invalid aliasing type is not directly UB, but
dereferencing the pointer is UB.</p>
</blockquote>
<pre><code class="language-cpp">short s[2] = { 1, 2 };

// Invalid aliasing (UB) - type punning, UB to deref ptr (int has stricter
// alignment requirements than short).
*reinterpret_cast&lt;int*&gt;(s);


// Arbitrary byte pointer.
char c[4] = { 1, 2, 3, 4 };

// Invalid aliasing (UB) - type punning, UB to deref ptr (int has stricter
// alignment requirements than char).
*reinterpret_cast&lt;int*&gt;(c);
</code></pre>
<p>At the time of writing, the current <a href="http://eel.is/c++draft/basic.lval#11">c++ std draft</a>
contains the following.</p>
<pre><code class="language-text">If a program attempts to access the stored value of an object through a glvalue
whose type is not **similar** (7.3.6) to one of the following types the
behavior is undefined [44]

(11.1) the dynamic type of the object,
(11.2) a type that is the signed or unsigned type corresponding to the dynamic
       type of the object, or
(11.3) a char, unsigned char, or std::byte type.

[44]: The intent of this list is to specify those circumstances in which an
      object can or cannot be aliased.
</code></pre>
<p>The paragraph is short but one also needs to understand the meaning of
<a href="http://eel.is/c++draft/conv.qual#def:similar_types">similar (<em>similar_types</em>)</a>.</p>
<p>This paragraph is actually somewhat more explicit in the <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf">c++17 std</a>.</p>
<pre><code class="language-text">If a program attempts to access the stored value of an object through a glvalue
of other than one of the following types the behavior is undefined [63]

(11.1) the dynamic type of the object,
(11.2) a cv-qualified version of the dynamic type of the object,
(11.3) a type similar (as defined in 7.5) to the dynamic type of the object,
(11.4) a type that is the signed or unsigned type corresponding to the dynamic
       type of the object,
(11.5) a type that is the signed or unsigned type corresponding to a
       cv-qualified version of the dynamic type of the object,
(11.6) an aggregate or union type that includes one of the aforementioned types
       among its elements or non- static data members (including, recursively,
       an element or non-static data member of a subaggregate or contained
       union),
(11.7) a type that is a (possibly cv-qualified) base class type of the dynamic
       type of the object,
(11.8) a char, unsigned char, or std::byte type.

[63]: The intent of this list is to specify those circumstances in which an
      object may or may not be aliased.
</code></pre>
<p>Additional references:</p>
<ul>
<li>
<p><a href="https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8">What is the Strict Aliasing Rule and Why do we care</a></p>
<p>The article shows a small example how the compiler may optimized using the
strict aliasing rules.</p>
<pre><code class="language-cpp">int alias(int* i, char* c) {
  *i = 1;
  *c = 'a';  // char* may alias int*
  return *i;
}

int noalias(int* i, short* s) {
    *i = 1;
    *s = 2;  // short* does not alias int*
    return *i;
}
</code></pre>
<pre><code class="language-x86asm">alias(int*, char*):
mov    DWORD PTR [rdi] ,0x1  ; *i = 1;
mov    BYTE PTR [rsi], 0x61  ; *c = 'a';
mov    eax,DWORD PTR [rdi]   ; Must reload, char* can alias int*.
ret

noalias(int*, short*):
mov    DWORD PTR [rdi], 0x1  ; *i = 1;
mov    WORD PTR [rsi], 0x2   ; *s = 2;
mov    eax,0x1               ; Must not reload, short* can not alias int*.
ret
</code></pre>
</li>
<li>
<p><a href="https://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing">reinterpret_cast</a> type aliasing</p>
<blockquote>
<ol start="5">
<li>Any object pointer type <code>T1*</code> can be converted to another object pointer
type <code>cv T2*</code>. This is exactly equivalent to <code>static_cast&lt;cv T2*&gt;(static_cast&lt;cv void*&gt;(expression))</code> (which implies that if T2's
alignment requirement is not stricter than T1's, the value of the pointer
does not change and conversion of the resulting pointer back to its
original type yields the original value). In any case, the resulting
pointer may only be dereferenced safely if allowed by the type aliasing
rules (see below).</li>
</ol>
</blockquote>
<pre><code class="language-cpp">int I;
char* X = reinterpret_cast&lt;char*&gt;(&amp;I);  // Valid, char allowed to alias int.
*X = 42;
int* Y = reinterpret_cast&lt;int*&gt;(X);     // Cast back to original type.
*Y = 1337;  // safe

char C[4];
int* P = reinterpret_cast&lt;int*&gt;(C);     // Cast is ok, not yet UB.
*P = 1337; // UB, violates strict aliasing / alignment rules.
           // https://stackoverflow.com/questions/52492229/c-byte-array-to-int
</code></pre>
</li>
<li>
<p>On <code>gcc</code> strict aliasing is enabled starting with <code>-O2</code>.</p>
<pre><code class="language-bash">for i in {0..3} g s; do echo &quot;-O$i $(g++ -Q --help=optimizers -O$i | grep fstrict-aliasing)&quot;; done
-O0   -fstrict-aliasing           [disabled]
-O1   -fstrict-aliasing           [disabled]
-O2   -fstrict-aliasing           [enabled]
-O3   -fstrict-aliasing           [enabled]
-Og   -fstrict-aliasing           [disabled]
-Os   -fstrict-aliasing           [enabled]
</code></pre>
</li>
</ul>
<h3 id="__restrict-keyword"><a class="header" href="#__restrict-keyword"><code>__restrict</code> keyword</a></h3>
<p>The <code>__restrict</code> keyword allows the programmer to tell the compiler that two
pointer will not alias each other.</p>
<pre><code class="language-cpp">int alias(int* a, int* b) {
    *a = 1;
    *b = 2;
    return *a;
}

// alias(int*, int*):                           # @alias(int*, int*)
//         mov     dword ptr [rdi], 1
//         mov     dword ptr [rsi], 2
//         mov     eax, dword ptr [rdi]
//         ret

int noalias(int* __restrict a, int* __restrict b) {
    *a = 1;
    *b = 2;
    return *a;
}

// noalias(int*, int*):                         # @noalias(int*, int*)
//         mov     dword ptr [rdi], 1
//         mov     dword ptr [rsi], 2
//         mov     eax, 1
//         ret
</code></pre>
<p>However this should only be used with care and in a narrow scope, as it is easy
to violate self defined contract, see <a href="https://godbolt.org/z/e8x1af3Mh">godbolt</a>.</p>
<h3 id="type-punning"><a class="header" href="#type-punning">Type punning</a></h3>
<p>The correct way to do <code>type-punning</code> in c++:</p>
<ol>
<li><a href="https://en.cppreference.com/w/cpp/numeric/bit_cast"><code>std::bit_cast</code></a> (c++20)</li>
<li><a href="https://godbolt.org/z/3PM4jGvEz"><code>std::memcpy</code></a></li>
</ol>
<h2 id="variadic-templates-parameter-pack"><a class="header" href="#variadic-templates-parameter-pack">Variadic templates (<a href="https://en.cppreference.com/w/cpp/language/parameter_pack">parameter pack</a>)</a></h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;

// -- Example 1 - print template value arguments.

// Base case with one parameter.
template&lt;int P&gt;
void show_int() {
    printf(&quot;%d\n&quot;, P);
}

// General case with at least two parameters, to disambiguate from base case.
template&lt;int P0, int P1, int... Params&gt;
void show_int() {
    printf(&quot;%d, &quot;, P0);
    show_int&lt;P1, Params...&gt;();
}

// -- Example 2 - print values of different types.

// Base case with one parameter.
template&lt;typename T&gt;
void show(const T&amp; t) {
    std::cout &lt;&lt; t &lt;&lt; '\n';
}

// General case with at least two parameters, to disambiguate from base case.
template&lt;typename T0, typename T1, typename... Types&gt;
void show(const T0&amp; t0, const T1&amp; t1, const Types&amp;... types) {
    std::cout &lt;&lt; t0 &lt;&lt; &quot;, &quot;;
    show(t1, types...);
}

int main() {
    show_int&lt;1, 2, 3, 4, 5&gt;();
    show(1, 1.0, &quot;foo&quot;, 'a');
}
</code></pre>
<h2 id="forwarding-reference-fwd-ref"><a class="header" href="#forwarding-reference-fwd-ref">Forwarding reference (<a href="https://en.cppreference.com/w/cpp/language/reference#Forwarding_references">fwd ref</a>)</a></h2>
<p>A <code>forwarding reference</code> is a special references that preserves the <code>value category</code> of a function parameter and therefore allows for <code>perfect</code>
forwarding.</p>
<p>A forwarding reference is a parameter of a function template, which is declared
as <code>rvalue</code> reference to a <code>non-cv</code> qualified <code>type</code> template parameter.</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
void fn(T&amp;&amp; param); // param is a forwarding reference
</code></pre>
<p>Perfect forwarding can be achieved with <a href="https://en.cppreference.com/w/cpp/utility/forward"><code>std::forward</code></a>. This for
example allows a wrapper function to pass a parameter with the <strong>exact</strong> same
value category to a down-stream function which is being invoked in the wrapper.</p>
<pre><code class="language-cpp">#include &lt;cstdio&gt;
#include &lt;utility&gt;

struct M {};

// -- CONSUMER -----------------------------------------------------------------

void use(M&amp;) {
    puts(__PRETTY_FUNCTION__);
}

void use(M&amp;&amp;) {
    puts(__PRETTY_FUNCTION__);
}

// -- TESTER -------------------------------------------------------------------

template&lt;typename T&gt;
void wrapper(T&amp;&amp; param) {  // forwarding reference
    puts(__PRETTY_FUNCTION__);
    // PARAM is an lvalue, therefore this always calls use(M&amp;).
    use(param);
}

template&lt;typename T&gt;
void fwd_wrapper(T&amp;&amp; param) {  // forwarding reference
    puts(__PRETTY_FUNCTION__);
    // PARAM is an lvalue, but std::forward returns PARAM with the same value
    // category as the forwarding reference takes.
    use(std::forward&lt;T&gt;(param));
}

// -- MAIN ---------------------------------------------------------------------

int main() {
    {
        std::puts(&quot;==&gt; wrapper rvalue reference&quot;);
        wrapper(M{});
        // calls use(M&amp;).

        std::puts(&quot;==&gt; wrapper lvalue reference&quot;);
        struct M m;
        wrapper(m);
        // calls use(M&amp;).
    }
    {
        std::puts(&quot;==&gt; fwd_wrapper rvalue reference&quot;);
        fwd_wrapper(M{});
        // calls use(M&amp;&amp;).

        std::puts(&quot;==&gt; fwd_wrapper lvalue reference&quot;);
        struct M m;
        fwd_wrapper(m);
        // calls use(M&amp;).
    }
}
</code></pre>
<h2 id="example-any_of-template-meta-function"><a class="header" href="#example-any_of-template-meta-function">Example: <code>any_of</code> template meta function</a></h2>
<pre><code class="language-cpp">#include &lt;type_traits&gt;

template&lt;typename T, typename... U&gt;
struct any_of : std::false_type {};

// Found our type T in the list of types U.
template&lt;typename T, typename... U&gt;
struct any_of&lt;T, T, U...&gt; : std::true_type {};

// Pop off the first element in the list of types U,
// since it didn't match our type T.
template&lt;typename T, typename U0, typename... U&gt;
struct any_of&lt;T, U0, U...&gt; : any_of&lt;T, U...&gt; {};

// Convenience template variable to invoke meta function.
template&lt;typename T, typename... U&gt;
constexpr bool any_of_v = any_of&lt;T, U...&gt;::value;

static_assert(any_of_v&lt;int, char, bool, int&gt;, &quot;&quot;);
static_assert(!any_of_v&lt;int, char, bool, float&gt;, &quot;&quot;);
</code></pre>
<h2 id="example-sfinae-enable_if"><a class="header" href="#example-sfinae-enable_if">Example: <a href="https://en.cppreference.com/w/cpp/language/sfinae">SFINAE</a> (<a href="https://en.cppreference.com/w/cpp/types/enable_if">enable_if</a>)</a></h2>
<p>Provide a single entry point <code>Invoke</code> to call some <code>Operations</code>.
Use <code>enable_if</code> to enable/disable the template functions depending on the two
available traits an operation can have:</p>
<ul>
<li>Operation returns a result</li>
<li>Operation requires a context</li>
</ul>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;type_traits&gt;

// Helper meta fns.

template&lt;typename T&gt;
using enable_if_bool = std::enable_if_t&lt;T::value, bool&gt;;

template&lt;typename T&gt;
using disable_if_bool = std::enable_if_t&lt;!T::value, bool&gt;;

template&lt;typename T&gt;
using has_dst = std::integral_constant&lt;bool, !std::is_same&lt;typename T::Return, void&gt;::value&gt;;

// Template meta programming invoke machinery.

namespace impl {
    // Invoke an OPERATION which *USES* a context.
    template&lt;typename Ctx, template&lt;typename&gt; class Op, typename... P,
             enable_if_bool&lt;typename Op&lt;Ctx&gt;::HasCtx&gt; = true&gt;
    typename Op&lt;Ctx&gt;::Return Invoke(const Ctx&amp; C, P... params) {
        return Op&lt;Ctx&gt;()(C, params...);
    }

    // Invoke an OPERATION which uses *NO* context.
    template&lt;typename Ctx, template&lt;typename&gt; class Op, typename... P,
             disable_if_bool&lt;typename Op&lt;Ctx&gt;::HasCtx&gt; = true&gt;
    typename Op&lt;Ctx&gt;::Return Invoke(const Ctx&amp;, P... params) {
        return Op&lt;Ctx&gt;()(params...);
    }
}  // namespace impl

// Invoke an OPERATION which *HAS* a DESTINATION with arbitrary number of arguments.
template&lt;typename Ctx, template&lt;typename&gt; class Op, typename... P,
         enable_if_bool&lt;has_dst&lt;Op&lt;Ctx&gt;&gt;&gt; = true&gt;
void Invoke(const Ctx&amp; C, P... params) {
    std::cout &lt;&lt; &quot;Invoke &quot; &lt;&lt; Op&lt;Ctx&gt;::Name &lt;&lt; '\n';
    typename Op&lt;Ctx&gt;::Return R = impl::Invoke&lt;Ctx, Op&gt;(C, params...);
    std::cout &lt;&lt; &quot;returned -&gt; &quot; &lt;&lt; R &lt;&lt; '\n';
}

// Invoke an OPERATION which has *NOT* a DESTINATION with arbitrary number of arguments.
template&lt;typename Ctx, template&lt;typename&gt; class Op, typename... P,
         disable_if_bool&lt;has_dst&lt;Op&lt;Ctx&gt;&gt;&gt; = true&gt;
void Invoke(const Ctx&amp; C, P... params) {
    std::cout &lt;&lt; &quot;Invoke &quot; &lt;&lt; Op&lt;Ctx&gt;::Name &lt;&lt; &quot; without destination.&quot; &lt;&lt; '\n';
    impl::Invoke&lt;Ctx, Op&gt;(C, params...);
}

// Custom context.

struct Ctx {
    void out(const char* s, unsigned v) const {
        printf(&quot;%s%x\n&quot;, s, v);
    }
};

// Operations to invoke.

template&lt;typename Ctx&gt;
struct OpA {
    using HasCtx = std::false_type;
    using Return = int;
    static constexpr const char* const Name = &quot;OpA&quot;;

    constexpr Return operator()(int a, int b) const {
        return a + b;
    }
};

template&lt;typename Ctx&gt;
struct OpB {
    using HasCtx = std::true_type;
    using Return = void;
    static constexpr const char* const Name = &quot;OpB&quot;;

    Return operator()(const Ctx&amp; C, unsigned a) const {
        C.out(&quot;a = &quot;, a);
    }
};

int main() {
    Ctx C;

    Invoke&lt;Ctx, OpA&gt;(C, 1, 2);
    Invoke&lt;Ctx, OpB&gt;(C, 0xf00du);

    return 0;
}
</code></pre>
<h2 id="example-minimal-templatized-test-registry"><a class="header" href="#example-minimal-templatized-test-registry">Example: Minimal templatized test registry</a></h2>
<p>A small test function registry bringing together a few different template
features.</p>
<pre><code class="language-cpp">#include &lt;cstdio&gt;
#include &lt;functional&gt;
#include &lt;map&gt;
#include &lt;string&gt;
#include &lt;type_traits&gt;

template&lt;typename R, typename... P&gt;
struct registry {
    using FUNC = R (*)(P...);
    using SELF = registry&lt;R, P...&gt;;
    using RET = R;

    static SELF&amp; get() {
        static SELF r;
        return r;
    }

    bool add(std::string nm, FUNC fn) {
        const auto r = m_fns.insert({std::move(nm), std::move(fn)});
        return r.second;
    }

    R invoke(const std::string&amp; nm, P... p) const {
        return invoke_impl&lt;R&gt;(nm, p...);
    }

    void dump() const {
        for (const auto&amp; it : m_fns) {
            std::puts(it.first.c_str());
        }
    }

  private:
    std::map&lt;std::string, FUNC&gt; m_fns;

    template&lt;typename RET&gt;
    std::enable_if_t&lt;std::is_same_v&lt;RET, void&gt;&gt; invoke_impl(const std::string&amp; nm, P... p) const {
        const auto it = m_fns.find(nm);
        if (it == m_fns.end()) {
            return;
        }
        std::invoke(it-&gt;second, p...);
    }

    template&lt;typename RET&gt;
    std::enable_if_t&lt;!std::is_same_v&lt;RET, void&gt;, RET&gt; invoke_impl(const std::string&amp; nm,
                                                                  P... p) const {
        const auto it = m_fns.find(nm);
        if (it == m_fns.end()) {
            static_assert(std::is_default_constructible_v&lt;RET&gt;,
                          &quot;RET must be default constructible&quot;);
            return {};
        }
        return std::invoke(it-&gt;second, p...);
    }
};

#define TEST_REGISTER(REGISTRY, NAME)                                                      \
    static bool regfn_##REGISTRY##NAME() {                                                 \
        const bool r = REGISTRY::get().add(#NAME, NAME);                                   \
        if (!r) {                                                                          \
            std::puts(&quot;Failed to register test &quot; #NAME &quot;, same name already registered!&quot;); \
            std::abort();                                                                  \
        }                                                                                  \
        return r;                                                                          \
    }                                                                                      \
    static const bool reg_##REGISTRY##NAME = regfn_##REGISTRY##NAME();

#define TEST(REGISTRY, NAME, ...)    \
    REGISTRY::RET NAME(__VA_ARGS__); \
    TEST_REGISTER(REGISTRY, NAME);   \
    REGISTRY::RET NAME(__VA_ARGS__)

// -- Usage 1 simple usage.

using REG1 = registry&lt;void&gt;;
TEST(REG1, test1) {
    std::puts(&quot;REG1::test1&quot;);
}
TEST(REG1, test2) {
    std::puts(&quot;REG1::test2&quot;);
}

// -- Usage 2 with convenience macro wrapper.

using REG2 = registry&lt;void, bool&gt;;
#define TEST2(NAME, ...) TEST(REG2, NAME, ##__VA_ARGS__)

TEST2(test1, bool val) {
    printf(&quot;REG2::test1 val %d\n&quot;, val);
}

int main() {
    const auto&amp; R1 = REG1::get();
    R1.dump();
    R1.invoke(&quot;test1&quot;);
    R1.invoke(&quot;test2&quot;);

    const auto&amp; R2 = REG2::get();
    R2.dump();
    R2.invoke(&quot;test1&quot;, true);

    return 0;
}
</code></pre>
<h2 id="example-concepts-pre-c20"><a class="header" href="#example-concepts-pre-c20">Example: Concepts pre c++20</a></h2>
<p>Prior to c++20's concepts, <code>SFINAE</code> and <code>std::void_t</code> can be leveraged to build
something similar allowing to define an interface (aka trait) for a template
parameter.</p>
<pre><code class="language-cpp">
template&lt;typename T, template&lt;typename&gt; class Checker, typename = void&gt;
struct is_valid : std::false_type {};

template&lt;typename T, template&lt;typename&gt; class Checker&gt;
struct is_valid&lt;T, Checker, std::void_t&lt;Checker&lt;T&gt;&gt;&gt; : std::true_type {};

template&lt;typename T, template&lt;typename&gt; class Checker&gt;
static constexpr bool is_valid_v = is_valid&lt;T, Checker&gt;::value;

// -----------------------------------------------------------------------------

template&lt;typename T, typename R, template&lt;typename&gt; class Checker, typename = void&gt;
struct is_valid_with_ret : std::false_type {};

template&lt;typename T, typename R, template&lt;typename&gt; class Checker&gt;
struct is_valid_with_ret&lt;T, R, Checker, std::void_t&lt;Checker&lt;T&gt;&gt;&gt; : std::is_same&lt;R, Checker&lt;T&gt;&gt; {};

template&lt;typename T, typename R, template&lt;typename&gt; class Checker&gt;
static constexpr bool is_valid_with_ret_v = is_valid_with_ret&lt;T, R, Checker&gt;::value;

// -----------------------------------------------------------------------------

template&lt;typename T&gt;
struct is_entry {
    template&lt;typename TT&gt;
    using init = decltype(std::declval&lt;TT&gt;().init());
    template&lt;typename TT&gt;
    using tag = decltype(std::declval&lt;TT&gt;().tag());
    template&lt;typename TT&gt;
    using val = decltype(std::declval&lt;TT&gt;().val());

    static constexpr bool value = is_valid_v&lt;T, init&gt; &amp;&amp; is_valid_with_ret_v&lt;T, int, tag&gt; &amp;&amp;
                                  is_valid_with_ret_v&lt;T, typename T::Type, val&gt;;
};

template&lt;typename T&gt;
static constexpr bool is_entry_v = is_entry&lt;T&gt;::value;

template&lt;typename E&gt;
struct Entry {
    using Type = E;
    void init();
    int tag() const;
    E val() const;
};

int main() {
    static_assert(is_entry_v&lt;Entry&lt;bool&gt;&gt;, &quot;&quot;);
}
</code></pre>
<p>The main mechanic can be explained with the following reduced example. If one
of the <code>decltype(std:declval&lt;T&gt;...</code> expressions is ill-formed, the template
specialization for <code>is_valid</code> will be removed from the candidate set due to
<a href="https://en.cppreference.com/w/cpp/language/sfinae">SFINAE</a>.</p>
<pre><code class="language-cpp">#include &lt;type_traits&gt;

// (1) Primary template.
template&lt;typename T, typename = void&gt;
struct is_valid : std::false_type {};

// (2) Partial template specialization.
template&lt;typename T&gt;
struct is_valid&lt;T, std::void_t&lt;decltype(std::declval&lt;T&gt;().some_fun1()),
                               decltype(std::declval&lt;T&gt;().some_fun2())&gt;&gt; : std::true_type {};
struct A {
    void some_fun1() {}
    void some_fun2() {}
};

struct B {};

static_assert(is_valid&lt;A&gt;::value, &quot;is true&quot;);
// * Compare template arg list with primary template, we only supplied one
//   arg, the second one will be defaulted as
//   is_valid&lt;A, void&gt;
// * Compare template arg list against available specializations, this will
//   try to match the pattern &lt;A, void&gt; against the patterns defined in the
//   partial specializations.
// * Try specialization (2)
//   * T -&gt; A
//   * Evaluate std::void_t -&gt; decltype's are well-formed
//     std::void_t&lt;...&gt; -&gt; void
//   * Specialization (2) matches &lt;A, void&gt;
// * Pick the most specialized version -&gt; (2)

static_assert(!is_valid&lt;B&gt;::value, &quot;is false&quot;);
// * Compare template arg list with primary template, we only supplied one
//   arg, the second one will be defaulted as
//   is_valid&lt;A, void&gt;
// * Compare template arg list against available specializations, this will
//   try to match the pattern &lt;B, void&gt; against the patterns defined in the
//   partial specializations.
// * Try specialization (2)
//   * T -&gt; B
//   * Evaluate std::void_t -&gt; decltype's are ill-formed
//   * Specialization (2) is removed from candidate set, no hard error (SFINAE)
// * No specialization matches, take the primary template.
</code></pre>
<blockquote>
<p><code>std::declval&lt;T&gt;()</code> creates an instance of type T in an unevaluated context.</p>
</blockquote>
<p>A more detailed description is available in the SO discussion <a href="https://stackoverflow.com/a/27688405">How does
<code>void_t</code> work</a>.</p>
<h2 id="template-selection-with-partially--fully-specializations"><a class="header" href="#template-selection-with-partially--fully-specializations">Template selection with partially / fully specializations.</a></h2>
<pre><code class="language-cpp">enum Kind {
    kPrimary,
    kTT,
    kIntBool,
    kIntInt,
};

// (1) Primary template.
template&lt;typename T, typename U = bool&gt;
struct pair {
    static constexpr Kind kind = kPrimary;
};

// (2) Partial template specialization.
template&lt;typename T&gt;
struct pair&lt;T, T&gt; {
    static constexpr Kind kind = kTT;
};

// (3) Template specialization.
template&lt;&gt;
struct pair&lt;int, bool&gt; {
    static constexpr Kind kind = kIntBool;
};

// (4) Template specialization.
template&lt;&gt;
struct pair&lt;int, int&gt; {
    static constexpr Kind kind = kIntInt;
};

int main() {
    static_assert(pair&lt;int&gt;::kind == kIntBool, &quot;&quot;);
    // * Compare template arg list with primary template, we only supplied one
    //   arg, the second one will be defaulted as
    //   pair&lt;int, bool&gt;
    // * Compare template arg list against available specializations, this will
    //   try to match the pattern &lt;int, bool&gt; against the patterns defined in the
    //   partial specializations.
    // * (2) &lt;int, bool&gt; pattern does not match
    // * (3) &lt;int, bool&gt; pattern does match
    // * (4) &lt;int, bool&gt; pattern does not match
    // * Pick the most specialized version -&gt; (3)

    static_assert(pair&lt;char, char&gt;::kind == kTT, &quot;&quot;);
    // * Compare template arg list against available specializations, this will
    //   try to match the pattern &lt;char, char&gt; against the patterns defined in the
    //   partial specializations.
    // * (2) &lt;char, char&gt; pattern does match
    // * (3) &lt;char, char&gt; pattern does not match
    // * (4) &lt;char, char&gt; pattern does not match
    // * Pick the most specialized version -&gt; (2)

    static_assert(pair&lt;int, int&gt;::kind == kIntInt, &quot;&quot;);
    // * Compare template arg list against available specializations, this will
    //   try to match the pattern &lt;int, int&gt; against the patterns defined in the
    //   partial specializations.
    // * (2) &lt;int, int&gt; pattern does match
    // * (3) &lt;int, int&gt; pattern does match
    // * (4) &lt;int, int&gt; pattern does not match
    // * Pick the most specialized version -&gt; (3)

    static_assert(pair&lt;char, short&gt;::kind == kPrimary, &quot;&quot;);
    // * Compare template arg list against available specializations, this will
    //   try to match the pattern &lt;char, short&gt; against the patterns defined in the
    //   partial specializations.
    // * (2) &lt;char, short&gt; pattern does not match
    // * (3) &lt;char, short&gt; pattern does not match
    // * (4) &lt;char, short&gt; pattern does not match
    // * No specialization matches, take the primary template.
}
</code></pre>
<h1 id="example-perfect-forwarding"><a class="header" href="#example-perfect-forwarding">Example: Perfect forwarding</a></h1>
<pre><code class="language-cpp">#include &lt;cassert&gt;
#include &lt;cstdio&gt;
#include &lt;new&gt;
#include &lt;type_traits&gt;
#include &lt;utility&gt;

struct S {};

struct M {
    M() {
        std::puts(&quot;M()&quot;);
    }
    M(const M&amp;) {
        std::puts(&quot;M(M&amp;)&quot;);
    }
    M(M&amp;&amp;) {
        std::puts(&quot;M(M&amp;&amp;)&quot;);
    }
    M&amp; operator=(const M&amp;) = delete;
    M&amp; operator=(M&amp;&amp;) = delete;

    M(S&amp;, int) {
        std::puts(&quot;M(S&amp;)&quot;);
    }
    M(S&amp;&amp;, int) {
        std::puts(&quot;M(S&amp;&amp;)&quot;);
    }
    ~M() {
        std::puts(&quot;~M()&quot;);
    }
};

template&lt;typename T&gt;
struct option {
    static_assert(!std::is_reference_v&lt;T&gt;);

    constexpr option() = default;

    template&lt;typename... Params&gt;
    constexpr option(Params&amp;&amp;... params) : m_has_val(true) {
        // BAD: does not perfectly forward!
        //      eg, if option(S&amp;&amp;) is invoked, this would invoke M(S&amp;).
        // new (&amp;m_val) T(params...);

        // GOOD: perfectly forwards params to constructor of T.
        new (m_val) T(std::forward&lt;Params&gt;(params)...);
    }

    ~option() {
        reset();
    }

    constexpr T&amp; value() {
        assert(m_has_val);
        // Placement new starts a new lifetime, launder pointer returned to the
        // aligned storage.
        //
        // [1] https://en.cppreference.com/w/cpp/utility/launder
        return *__builtin_launder(reinterpret_cast&lt;T*&gt;(m_val));
    }

  private:
    constexpr void reset() {
        if (!m_has_val) {
            return;
        }
        if constexpr (!std::is_trivially_destructible_v&lt;T&gt;) {
            value().~T();
        };
    }

    alignas(T) char m_val[sizeof(T)];
    bool m_has_val{false};
};

int main() {
    std::puts(&quot;==&gt; case 1&quot;);
    // invokes M(S&amp;&amp;, int)
    option&lt;M&gt; opt1(S{}, 123);

    std::puts(&quot;==&gt; case 2&quot;);
    // invokes M() + M(M&amp;&amp;)
    option&lt;M&gt; x /* option(M&amp;&amp;) + M(M&amp;&amp;) */ = M{} /* M() */;
}
</code></pre>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../development/c++filt.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next prefetch" href="../development/glibc.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../development/c++filt.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next prefetch" href="../development/glibc.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="../elasticlunr.min.js"></script>
        <script src="../mark.min.js"></script>
        <script src="../searcher.js"></script>

        <script src="../clipboard.min.js"></script>
        <script src="../highlight.js"></script>
        <script src="../book.js"></script>

        <!-- Custom JS scripts -->


    </div>
    </body>
</html>