CINXE.COM
December 2013 – Sutter’s Mill
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="profile" href="http://gmpg.org/xfn/11"> <title>December 2013 – Sutter’s Mill</title> <script type="text/javascript"> WebFontConfig = {"google":{"families":["Alegreya+Sans:r:latin,latin-ext","Noticia+Text:r,i,b,bi:latin,latin-ext"]},"api_url":"https:\/\/fonts-api.wp.com\/css"}; (function() { var wf = document.createElement('script'); wf.src = 'https://s0.wp.com/wp-content/plugins/custom-fonts/js/webfont.js'; wf.type = 'text/javascript'; wf.async = 'true'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(wf, s); })(); </script><style id="jetpack-custom-fonts-css">.wf-active code, .wf-active kbd, .wf-active pre, .wf-active samp{font-family:"Noticia Text",serif}.wf-active body{font-family:"Noticia Text",serif}.wf-active button, .wf-active input, .wf-active select{font-family:"Noticia Text",serif}.wf-active textarea{font-family:"Noticia Text",serif}.wf-active blockquote{font-family:"Noticia Text",serif}.wf-active code, .wf-active kbd, .wf-active pre, .wf-active tt, .wf-active var{font-family:"Noticia Text",serif}.wf-active .button, .wf-active .more-link, .wf-active button:not(.menu-toggle), .wf-active input[type="button"], .wf-active input[type="reset"], .wf-active input[type="submit"], .wf-active .posts-navigation .nav-links a, .wf-active #content #infinite-handle span button{font-family:"Noticia Text",serif}.wf-active input[type="email"], .wf-active input[type="password"], .wf-active input[type="search"], .wf-active input[type="text"], .wf-active input[type="url"], .wf-active textarea{font-family:"Noticia Text",serif}.wf-active .post-navigation{font-family:"Noticia Text",serif}.wf-active .main-navigation{font-family:"Noticia Text",serif}.wf-active .entry-content, .wf-active .entry-summary, .wf-active .page-content{font-family:"Noticia Text",serif}.wf-active .entry-content .subtitle{font-family:"Noticia Text",serif}.wf-active #comments{font-family:"Noticia Text",serif}.wf-active .comment-form label{font-family:"Noticia Text",serif}.wf-active .comment-form span.required{font-family:"Noticia Text",serif}.wf-active .widget_recent_entries span.post-date{font-family:"Noticia Text",serif}.wf-active .site-description{font-family:"Noticia Text",serif}.wf-active .site-posted-on time{font-family:"Noticia Text",serif}.wf-active .page-header:not(.page-header-light) .taxonomy-description{font-family:"Noticia Text",serif}.wf-active .light-text{font-family:"Noticia Text",serif}.wf-active .site-info{font-family:"Noticia Text",serif}.wf-active .sticky-label{font-family:"Noticia Text",serif}.wf-active .post-details, .wf-active .post-details a{font-family:"Noticia Text",serif}.wf-active .page-links{font-family:"Noticia Text",serif}.wf-active .post-edit-link{font-family:"Noticia Text",serif}.wf-active .post-author-card .author-description{font-family:"Noticia Text",serif}.wf-active #tinymce h1, .wf-active #tinymce h2, .wf-active #tinymce h3, .wf-active #tinymce h4, .wf-active #tinymce h5, .wf-active #tinymce h6, .wf-active .comment-content h1, .wf-active .comment-content h2, .wf-active .comment-content h3, .wf-active .comment-content h4, .wf-active .comment-content h5, .wf-active .comment-content h6, .wf-active .entry-content h1, .wf-active .entry-content h2, .wf-active .entry-content h3, .wf-active .entry-content h4, .wf-active .entry-content h5, .wf-active .entry-content h6, .wf-active .entry-summary h1, .wf-active .entry-summary h2, .wf-active .entry-summary h3, .wf-active .entry-summary h4, .wf-active .entry-summary h5, .wf-active .entry-summary h6, .wf-active .widget_text h1, .wf-active .widget_text h2, .wf-active .widget_text h3, .wf-active .widget_text h4, .wf-active .widget_text h5, .wf-active .widget_text h6{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active h1{font-style:normal;font-weight:400}.wf-active h2{font-style:normal;font-weight:400}.wf-active h3{font-style:normal;font-weight:400}.wf-active h4{font-style:normal;font-weight:400}.wf-active h5{font-style:normal;font-weight:400}.wf-active h6{font-style:normal;font-weight:400}.wf-active blockquote h1, .wf-active blockquote h2, .wf-active blockquote h3, .wf-active blockquote h4{font-family:"Alegreya Sans",sans-serif;font-weight:400;font-style:normal}.wf-active div#jp-relatedposts h3.jp-relatedposts-headline em{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active .comment-reply-title, .wf-active .comments-title{font-family:"Alegreya Sans",sans-serif;font-weight:400;font-style:normal}.wf-active .image-post-title{font-family:"Alegreya Sans",sans-serif;font-weight:400;font-style:normal}.wf-active .page-header:not(.page-header-light) h1{font-style:normal;font-weight:400}.wf-active .entry-title{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active #post-cover-image .cover-meta .single-post-title{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active #hero-header .site-title{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active .site-header .site-title{font-style:normal;font-weight:400}.wf-active .site-header .site-description{font-style:normal;font-weight:400}</style> <meta name='robots' content='max-image-preview:large' /> <!-- Async WordPress.com Remote Login --> <script id="wpcom_remote_login_js"> var wpcom_remote_login_extra_auth = ''; function wpcom_remote_login_remove_dom_node_id( element_id ) { var dom_node = document.getElementById( element_id ); if ( dom_node ) { dom_node.parentNode.removeChild( dom_node ); } } function wpcom_remote_login_remove_dom_node_classes( class_name ) { var dom_nodes = document.querySelectorAll( '.' + class_name ); for ( var i = 0; i < dom_nodes.length; i++ ) { dom_nodes[ i ].parentNode.removeChild( dom_nodes[ i ] ); } } function wpcom_remote_login_final_cleanup() { wpcom_remote_login_remove_dom_node_classes( "wpcom_remote_login_msg" ); wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" ); wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_validate" ); wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_js" ); wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_iframe" ); wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_styles" ); } // Watch for messages back from the remote login window.addEventListener( "message", function( e ) { if ( e.origin === "https://r-login.wordpress.com" ) { var data = {}; try { data = JSON.parse( e.data ); } catch( e ) { wpcom_remote_login_final_cleanup(); return; } if ( data.msg === 'LOGIN' ) { // Clean up the login check iframe wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" ); var id_regex = new RegExp( /^[0-9]+$/ ); var token_regex = new RegExp( /^.*|.*|.*$/ ); if ( token_regex.test( data.token ) && id_regex.test( data.wpcomid ) ) { // We have everything we need to ask for a login var script = document.createElement( "script" ); script.setAttribute( "id", "wpcom_remote_login_validate" ); script.src = '/remote-login.php?wpcom_remote_login=validate' + '&wpcomid=' + data.wpcomid + '&token=' + encodeURIComponent( data.token ) + '&host=' + window.location.protocol + '//' + window.location.hostname + '&postid=2387' + '&is_singular='; document.body.appendChild( script ); } return; } // Safari ITP, not logged in, so redirect if ( data.msg === 'LOGIN-REDIRECT' ) { window.location = 'https://wordpress.com/log-in?redirect_to=' + window.location.href; return; } // Safari ITP, storage access failed, remove the request if ( data.msg === 'LOGIN-REMOVE' ) { var css_zap = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } @media screen and ( max-width: 782px ) { html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } }'; var style_zap = document.createElement( 'style' ); style_zap.type = 'text/css'; style_zap.appendChild( document.createTextNode( css_zap ) ); document.body.appendChild( style_zap ); var e = document.getElementById( 'wpcom_request_access_iframe' ); e.parentNode.removeChild( e ); document.cookie = 'wordpress_com_login_access=denied; path=/; max-age=31536000'; return; } // Safari ITP if ( data.msg === 'REQUEST_ACCESS' ) { console.log( 'request access: safari' ); // Check ITP iframe enable/disable knob if ( wpcom_remote_login_extra_auth !== 'safari_itp_iframe' ) { return; } // If we are in a "private window" there is no ITP. var private_window = false; try { var opendb = window.openDatabase( null, null, null, null ); } catch( e ) { private_window = true; } if ( private_window ) { console.log( 'private window' ); return; } var iframe = document.createElement( 'iframe' ); iframe.id = 'wpcom_request_access_iframe'; iframe.setAttribute( 'scrolling', 'no' ); iframe.setAttribute( 'sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-top-navigation-by-user-activation' ); iframe.src = 'https://r-login.wordpress.com/remote-login.php?wpcom_remote_login=request_access&origin=' + encodeURIComponent( data.origin ) + '&wpcomid=' + encodeURIComponent( data.wpcomid ); var css = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 46px !important; } * html body { margin-top: 46px !important; } @media screen and ( max-width: 660px ) { html { margin-top: 71px !important; } * html body { margin-top: 71px !important; } #wpcom_request_access_iframe { display: block; height: 71px !important; } } #wpcom_request_access_iframe { border: 0px; height: 46px; position: fixed; top: 0; left: 0; width: 100%; min-width: 100%; z-index: 99999; background: #23282d; } '; var style = document.createElement( 'style' ); style.type = 'text/css'; style.id = 'wpcom_request_access_styles'; style.appendChild( document.createTextNode( css ) ); document.body.appendChild( style ); document.body.appendChild( iframe ); } if ( data.msg === 'DONE' ) { wpcom_remote_login_final_cleanup(); } } }, false ); // Inject the remote login iframe after the page has had a chance to load // more critical resources window.addEventListener( "DOMContentLoaded", function( e ) { var iframe = document.createElement( "iframe" ); iframe.style.display = "none"; iframe.setAttribute( "scrolling", "no" ); iframe.setAttribute( "id", "wpcom_remote_login_key" ); iframe.src = "https://r-login.wordpress.com/remote-login.php" + "?wpcom_remote_login=key" + "&origin=aHR0cHM6Ly9oZXJic3V0dGVyLmNvbQ%3D%3D" + "&wpcomid=3379246" + "&time=1740573911"; document.body.appendChild( iframe ); }, false ); </script> <link rel='dns-prefetch' href='//s2.wp.com' /> <link rel='dns-prefetch' href='//s1.wp.com' /> <link rel='dns-prefetch' href='//s0.wp.com' /> <link rel="alternate" type="application/rss+xml" title="Sutter’s Mill » Feed" href="https://herbsutter.com/feed/" /> <link rel="alternate" type="application/rss+xml" title="Sutter’s Mill » Comments Feed" href="https://herbsutter.com/comments/feed/" /> <script type="text/javascript"> /* <![CDATA[ */ function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function () { oldonload(); func(); } } } /* ]]> */ </script> <script type="text/javascript"> /* <![CDATA[ */ window._wpemojiSettings = {"baseUrl":"https:\/\/s0.wp.com\/wp-content\/mu-plugins\/wpcom-smileys\/twemoji\/2\/72x72\/","ext":".png","svgUrl":"https:\/\/s0.wp.com\/wp-content\/mu-plugins\/wpcom-smileys\/twemoji\/2\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/s2.wp.com\/wp-includes\/js\/wp-emoji-release.min.js?m=1719498190i&ver=6.7.2-RC1-59780"}}; /*! This file is auto-generated */ !function(i,n){var o,s,e;function c(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function p(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data),r=(e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0),new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data));return t.every(function(e,t){return e===r[t]})}function u(e,t,n){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\uddfa\ud83c\uddf3","\ud83c\uddfa\u200b\ud83c\uddf3")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!n(e,"\ud83d\udc26\u200d\u2b1b","\ud83d\udc26\u200b\u2b1b")}return!1}function f(e,t,n){var r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):i.createElement("canvas"),a=r.getContext("2d",{willReadFrequently:!0}),o=(a.textBaseline="top",a.font="600 32px Arial",{});return e.forEach(function(e){o[e]=t(a,e,n)}),o}function t(e){var t=i.createElement("script");t.src=e,t.defer=!0,i.head.appendChild(t)}"undefined"!=typeof Promise&&(o="wpEmojiSettingsSupports",s=["flag","emoji"],n.supports={everything:!0,everythingExceptFlag:!0},e=new Promise(function(e){i.addEventListener("DOMContentLoaded",e,{once:!0})}),new Promise(function(t){var n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"}),a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=function(e){c(n=e.data),a.terminate(),t(n)})}catch(e){}c(n=f(s,u,p))}t(n)}).then(function(e){for(var t in e)n.supports[t]=e[t],n.supports.everything=n.supports.everything&&n.supports[t],"flag"!==t&&(n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&n.supports[t]);n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&!n.supports.flag,n.DOMReady=!1,n.readyCallback=function(){n.DOMReady=!0}}).then(function(){return e}).then(function(){var e;n.supports.everything||(n.readyCallback(),(e=n.source||{}).concatemoji?t(e.concatemoji):e.wpemoji&&e.twemoji&&(t(e.twemoji),t(e.wpemoji)))}))}((window,document),window._wpemojiSettings); /* ]]> */ </script> <style id='wp-emoji-styles-inline-css'> img.wp-smiley, img.emoji { display: inline !important; border: none !important; box-shadow: none !important; height: 1em !important; width: 1em !important; margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; } </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-2-1' href='https://s1.wp.com/_static/??-eJyljkEKwyAQRS9UMxoCWZWeRc1gTY3KzNjg7Zt2U+gq0OXn8R4f9qp8yYJZoKYWYmYI7ZgOKRyEEJ6jHvQwgmsxLeBS8Q+VoiNLHVh6wsEzX+C/kNxxOxP6WAwrSrVv3fbSRAWKy+kvPwmyEnPgr37brmaetNaTMfP6AnHzajo=&cssminify=yes' type='text/css' media='all' /> <style id='wp-block-library-inline-css'> .has-text-align-justify { text-align:justify; } .has-text-align-justify{text-align:justify;} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-4-1' href='https://s2.wp.com/_static/??-eJzTLy/QzcxLzilNSS3WzyrWz01NyUxMzUnNTc0rQeEU5CRWphbp5qSmJyZX6uVm5uklFxfr6OPTDpRD5sM02efaGpoZmFkYGRuZGmQBAHPvL0Y=&cssminify=yes' type='text/css' media='all' /> <style id='jetpack-sharing-buttons-style-inline-css'> .jetpack-sharing-buttons__services-list{display:flex;flex-direction:row;flex-wrap:wrap;gap:0;list-style-type:none;margin:5px;padding:0}.jetpack-sharing-buttons__services-list.has-small-icon-size{font-size:12px}.jetpack-sharing-buttons__services-list.has-normal-icon-size{font-size:16px}.jetpack-sharing-buttons__services-list.has-large-icon-size{font-size:24px}.jetpack-sharing-buttons__services-list.has-huge-icon-size{font-size:36px}@media print{.jetpack-sharing-buttons__services-list{display:none!important}}.editor-styles-wrapper .wp-block-jetpack-sharing-buttons{gap:0;padding-inline-start:0}ul.jetpack-sharing-buttons__services-list.has-background{padding:1.25em 2.375em} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-6-1' href='https://s2.wp.com/wp-content/plugins/coblocks/2.18.1-simple-rev.4/dist/coblocks-style.css?m=1681832297i&cssminify=yes' type='text/css' media='all' /> <style id='classic-theme-styles-inline-css'> /*! This file is auto-generated */ .wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-8-1' href='https://s1.wp.com/_static/??/wp-content/mu-plugins/core-compat/wp-mediaelement.css,/wp-content/mu-plugins/wpcom-bbpress-premium-themes.css?m=1432920480j&cssminify=yes' type='text/css' media='all' /> <style id='global-styles-inline-css'> :root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #fff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--medium-blue: #0087be;--wp--preset--color--bright-blue: #00aadc;--wp--preset--color--dark-gray: #4d4d4b;--wp--preset--color--light-gray: #b3b3b1;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--font-family--albert-sans: 'Albert Sans', sans-serif;--wp--preset--font-family--alegreya: Alegreya, serif;--wp--preset--font-family--arvo: Arvo, serif;--wp--preset--font-family--bodoni-moda: 'Bodoni Moda', serif;--wp--preset--font-family--bricolage-grotesque: 'Bricolage Grotesque', sans-serif;--wp--preset--font-family--cabin: Cabin, sans-serif;--wp--preset--font-family--chivo: Chivo, sans-serif;--wp--preset--font-family--commissioner: Commissioner, sans-serif;--wp--preset--font-family--cormorant: Cormorant, serif;--wp--preset--font-family--courier-prime: 'Courier Prime', monospace;--wp--preset--font-family--crimson-pro: 'Crimson Pro', serif;--wp--preset--font-family--dm-mono: 'DM Mono', monospace;--wp--preset--font-family--dm-sans: 'DM Sans', sans-serif;--wp--preset--font-family--dm-serif-display: 'DM Serif Display', serif;--wp--preset--font-family--domine: Domine, serif;--wp--preset--font-family--eb-garamond: 'EB Garamond', serif;--wp--preset--font-family--epilogue: Epilogue, sans-serif;--wp--preset--font-family--fahkwang: Fahkwang, sans-serif;--wp--preset--font-family--figtree: Figtree, sans-serif;--wp--preset--font-family--fira-sans: 'Fira Sans', sans-serif;--wp--preset--font-family--fjalla-one: 'Fjalla One', sans-serif;--wp--preset--font-family--fraunces: Fraunces, serif;--wp--preset--font-family--gabarito: Gabarito, system-ui;--wp--preset--font-family--ibm-plex-mono: 'IBM Plex Mono', monospace;--wp--preset--font-family--ibm-plex-sans: 'IBM Plex Sans', sans-serif;--wp--preset--font-family--ibarra-real-nova: 'Ibarra Real Nova', serif;--wp--preset--font-family--instrument-serif: 'Instrument Serif', serif;--wp--preset--font-family--inter: Inter, sans-serif;--wp--preset--font-family--josefin-sans: 'Josefin Sans', sans-serif;--wp--preset--font-family--jost: Jost, sans-serif;--wp--preset--font-family--libre-baskerville: 'Libre Baskerville', serif;--wp--preset--font-family--libre-franklin: 'Libre Franklin', sans-serif;--wp--preset--font-family--literata: Literata, serif;--wp--preset--font-family--lora: Lora, serif;--wp--preset--font-family--merriweather: Merriweather, serif;--wp--preset--font-family--montserrat: Montserrat, sans-serif;--wp--preset--font-family--newsreader: Newsreader, serif;--wp--preset--font-family--noto-sans-mono: 'Noto Sans Mono', sans-serif;--wp--preset--font-family--nunito: Nunito, sans-serif;--wp--preset--font-family--open-sans: 'Open Sans', sans-serif;--wp--preset--font-family--overpass: Overpass, sans-serif;--wp--preset--font-family--pt-serif: 'PT Serif', serif;--wp--preset--font-family--petrona: Petrona, serif;--wp--preset--font-family--piazzolla: Piazzolla, serif;--wp--preset--font-family--playfair-display: 'Playfair Display', serif;--wp--preset--font-family--plus-jakarta-sans: 'Plus Jakarta Sans', sans-serif;--wp--preset--font-family--poppins: Poppins, sans-serif;--wp--preset--font-family--raleway: Raleway, sans-serif;--wp--preset--font-family--roboto: Roboto, sans-serif;--wp--preset--font-family--roboto-slab: 'Roboto Slab', serif;--wp--preset--font-family--rubik: Rubik, sans-serif;--wp--preset--font-family--rufina: Rufina, serif;--wp--preset--font-family--sora: Sora, sans-serif;--wp--preset--font-family--source-sans-3: 'Source Sans 3', sans-serif;--wp--preset--font-family--source-serif-4: 'Source Serif 4', serif;--wp--preset--font-family--space-mono: 'Space Mono', monospace;--wp--preset--font-family--syne: Syne, sans-serif;--wp--preset--font-family--texturina: Texturina, serif;--wp--preset--font-family--urbanist: Urbanist, sans-serif;--wp--preset--font-family--work-sans: 'Work Sans', sans-serif;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-albert-sans-font-family{font-family: var(--wp--preset--font-family--albert-sans) !important;}.has-alegreya-font-family{font-family: var(--wp--preset--font-family--alegreya) !important;}.has-arvo-font-family{font-family: var(--wp--preset--font-family--arvo) !important;}.has-bodoni-moda-font-family{font-family: var(--wp--preset--font-family--bodoni-moda) !important;}.has-bricolage-grotesque-font-family{font-family: var(--wp--preset--font-family--bricolage-grotesque) !important;}.has-cabin-font-family{font-family: var(--wp--preset--font-family--cabin) !important;}.has-chivo-font-family{font-family: var(--wp--preset--font-family--chivo) !important;}.has-commissioner-font-family{font-family: var(--wp--preset--font-family--commissioner) !important;}.has-cormorant-font-family{font-family: var(--wp--preset--font-family--cormorant) !important;}.has-courier-prime-font-family{font-family: var(--wp--preset--font-family--courier-prime) !important;}.has-crimson-pro-font-family{font-family: var(--wp--preset--font-family--crimson-pro) !important;}.has-dm-mono-font-family{font-family: var(--wp--preset--font-family--dm-mono) !important;}.has-dm-sans-font-family{font-family: var(--wp--preset--font-family--dm-sans) !important;}.has-dm-serif-display-font-family{font-family: var(--wp--preset--font-family--dm-serif-display) !important;}.has-domine-font-family{font-family: var(--wp--preset--font-family--domine) !important;}.has-eb-garamond-font-family{font-family: var(--wp--preset--font-family--eb-garamond) !important;}.has-epilogue-font-family{font-family: var(--wp--preset--font-family--epilogue) !important;}.has-fahkwang-font-family{font-family: var(--wp--preset--font-family--fahkwang) !important;}.has-figtree-font-family{font-family: var(--wp--preset--font-family--figtree) !important;}.has-fira-sans-font-family{font-family: var(--wp--preset--font-family--fira-sans) !important;}.has-fjalla-one-font-family{font-family: var(--wp--preset--font-family--fjalla-one) !important;}.has-fraunces-font-family{font-family: var(--wp--preset--font-family--fraunces) !important;}.has-gabarito-font-family{font-family: var(--wp--preset--font-family--gabarito) !important;}.has-ibm-plex-mono-font-family{font-family: var(--wp--preset--font-family--ibm-plex-mono) !important;}.has-ibm-plex-sans-font-family{font-family: var(--wp--preset--font-family--ibm-plex-sans) !important;}.has-ibarra-real-nova-font-family{font-family: var(--wp--preset--font-family--ibarra-real-nova) !important;}.has-instrument-serif-font-family{font-family: var(--wp--preset--font-family--instrument-serif) !important;}.has-inter-font-family{font-family: var(--wp--preset--font-family--inter) !important;}.has-josefin-sans-font-family{font-family: var(--wp--preset--font-family--josefin-sans) !important;}.has-jost-font-family{font-family: var(--wp--preset--font-family--jost) !important;}.has-libre-baskerville-font-family{font-family: var(--wp--preset--font-family--libre-baskerville) !important;}.has-libre-franklin-font-family{font-family: var(--wp--preset--font-family--libre-franklin) !important;}.has-literata-font-family{font-family: var(--wp--preset--font-family--literata) !important;}.has-lora-font-family{font-family: var(--wp--preset--font-family--lora) !important;}.has-merriweather-font-family{font-family: var(--wp--preset--font-family--merriweather) !important;}.has-montserrat-font-family{font-family: var(--wp--preset--font-family--montserrat) !important;}.has-newsreader-font-family{font-family: var(--wp--preset--font-family--newsreader) !important;}.has-noto-sans-mono-font-family{font-family: var(--wp--preset--font-family--noto-sans-mono) !important;}.has-nunito-font-family{font-family: var(--wp--preset--font-family--nunito) !important;}.has-open-sans-font-family{font-family: var(--wp--preset--font-family--open-sans) !important;}.has-overpass-font-family{font-family: var(--wp--preset--font-family--overpass) !important;}.has-pt-serif-font-family{font-family: var(--wp--preset--font-family--pt-serif) !important;}.has-petrona-font-family{font-family: var(--wp--preset--font-family--petrona) !important;}.has-piazzolla-font-family{font-family: var(--wp--preset--font-family--piazzolla) !important;}.has-playfair-display-font-family{font-family: var(--wp--preset--font-family--playfair-display) !important;}.has-plus-jakarta-sans-font-family{font-family: var(--wp--preset--font-family--plus-jakarta-sans) !important;}.has-poppins-font-family{font-family: var(--wp--preset--font-family--poppins) !important;}.has-raleway-font-family{font-family: var(--wp--preset--font-family--raleway) !important;}.has-roboto-font-family{font-family: var(--wp--preset--font-family--roboto) !important;}.has-roboto-slab-font-family{font-family: var(--wp--preset--font-family--roboto-slab) !important;}.has-rubik-font-family{font-family: var(--wp--preset--font-family--rubik) !important;}.has-rufina-font-family{font-family: var(--wp--preset--font-family--rufina) !important;}.has-sora-font-family{font-family: var(--wp--preset--font-family--sora) !important;}.has-source-sans-3-font-family{font-family: var(--wp--preset--font-family--source-sans-3) !important;}.has-source-serif-4-font-family{font-family: var(--wp--preset--font-family--source-serif-4) !important;}.has-space-mono-font-family{font-family: var(--wp--preset--font-family--space-mono) !important;}.has-syne-font-family{font-family: var(--wp--preset--font-family--syne) !important;}.has-texturina-font-family{font-family: var(--wp--preset--font-family--texturina) !important;}.has-urbanist-font-family{font-family: var(--wp--preset--font-family--urbanist) !important;}.has-work-sans-font-family{font-family: var(--wp--preset--font-family--work-sans) !important;} :where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;} :root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;} :where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-10-1' href='https://s0.wp.com/_static/??-eJydj70OgzAMhF+oqfsDZar6KFUxFgQSx8KOUN++AXXo0InldDd8dzpYxGFiIzaI2UnIvWeFkUxeOH0zaGZ4ekboiWn2BdD/9oiqB/jptIEiKUhuwXNHQkXYXMnB60Czu4DaO9AesCDQhoTTrtn1zjbtFsEU14pHvJ+ba3Or6lNdjR/JRGmL&cssminify=yes' type='text/css' media='all' /> <style id='independent-publisher-2-style-inline-css'> .cat-links, .post-tags, .tags-links { clip: rect(1px, 1px, 1px, 1px); height: 1px; position: absolute; overflow: hidden; width: 1px; } </style> <style id='akismet-widget-style-inline-css'> .a-stats { --akismet-color-mid-green: #357b49; --akismet-color-white: #fff; --akismet-color-light-grey: #f6f7f7; max-width: 350px; width: auto; } .a-stats * { all: unset; box-sizing: border-box; } .a-stats strong { font-weight: 600; } .a-stats a.a-stats__link, .a-stats a.a-stats__link:visited, .a-stats a.a-stats__link:active { background: var(--akismet-color-mid-green); border: none; box-shadow: none; border-radius: 8px; color: var(--akismet-color-white); cursor: pointer; display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen-Sans', 'Ubuntu', 'Cantarell', 'Helvetica Neue', sans-serif; font-weight: 500; padding: 12px; text-align: center; text-decoration: none; transition: all 0.2s ease; } /* Extra specificity to deal with TwentyTwentyOne focus style */ .widget .a-stats a.a-stats__link:focus { background: var(--akismet-color-mid-green); color: var(--akismet-color-white); text-decoration: none; } .a-stats a.a-stats__link:hover { filter: brightness(110%); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06), 0 0 2px rgba(0, 0, 0, 0.16); } .a-stats .count { color: var(--akismet-color-white); display: block; font-size: 1.5em; line-height: 1.4; padding: 0 13px; white-space: nowrap; } </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-12-1' href='https://s1.wp.com/_static/??-eJzTLy/QTc7PK0nNK9HPLdUtyClNz8wr1i9KTcrJTwcy0/WTi5G5ekCujj52Temp+bo5+cmJJZn5eSgc3bScxMwikFb7XFtDE1NLExMLc0OTLACohS2q&cssminify=yes' type='text/css' media='all' /> <link crossorigin='anonymous' rel='stylesheet' id='print-css-13-1' href='https://s1.wp.com/wp-content/mu-plugins/global-print/global-print.css?m=1465851035i&cssminify=yes' type='text/css' media='print' /> <style id='jetpack-global-styles-frontend-style-inline-css'> :root { --font-headings: unset; --font-base: unset; --font-headings-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; --font-base-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-16-1' href='https://s2.wp.com/wp-content/themes/h4/global.css?m=1420737423i&cssminify=yes' type='text/css' media='all' /> <script type="text/javascript" id="wpcom-actionbar-placeholder-js-extra"> /* <![CDATA[ */ var actionbardata = {"siteID":"3379246","postID":"0","siteURL":"https:\/\/herbsutter.com","xhrURL":"https:\/\/herbsutter.com\/wp-admin\/admin-ajax.php","nonce":"7f4d393db3","isLoggedIn":"","statusMessage":"","subsEmailDefault":"instantly","proxyScriptUrl":"https:\/\/s0.wp.com\/wp-content\/js\/wpcom-proxy-request.js?ver=20211021","i18n":{"followedText":"New posts from this site will now appear in your <a href=\"https:\/\/wordpress.com\/reader\">Reader<\/a>","foldBar":"Collapse this bar","unfoldBar":"Expand this bar","shortLinkCopied":"Shortlink copied to clipboard."}}; /* ]]> */ </script> <script type="text/javascript" id="jetpack-mu-wpcom-settings-js-before"> /* <![CDATA[ */ var JETPACK_MU_WPCOM_SETTINGS = {"assetsUrl":"https:\/\/s1.wp.com\/wp-content\/mu-plugins\/jetpack-mu-wpcom-plugin\/sun\/jetpack_vendor\/automattic\/jetpack-mu-wpcom\/src\/build\/"}; /* ]]> */ </script> <script crossorigin='anonymous' type='text/javascript' src='https://s2.wp.com/_static/??-eJzTLy/QzcxLzilNSS3WzwKiwtLUokoopZebmaeXVayjj0+Rbm5melFiSSqy4uT8vJLUvBJMA8sLkvNzdQuK8isqdYtSgWLFJVj0FOWUQNQA5exzbQ3NjQxMjQ3MLCyzAMS4QKo='></script> <script type="text/javascript" id="rlt-proxy-js-after"> /* <![CDATA[ */ rltInitialize( {"token":null,"iframeOrigins":["https:\/\/widgets.wp.com"]} ); /* ]]> */ </script> <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://herbsutter.wordpress.com/xmlrpc.php?rsd" /> <meta name="generator" content="WordPress.com" /> <!-- Jetpack Open Graph Tags --> <meta property="og:type" content="website" /> <meta property="og:title" content="December 2013 – Sutter’s Mill" /> <meta property="og:site_name" content="Sutter’s Mill" /> <meta property="og:image" content="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=200&ts=1740573911" /> <meta property="og:image:width" content="200" /> <meta property="og:image:height" content="200" /> <meta property="og:image:alt" content="" /> <meta property="og:locale" content="en_US" /> <!-- End Jetpack Open Graph Tags --> <link rel="shortcut icon" type="image/x-icon" href="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=32" sizes="16x16" /> <link rel="icon" type="image/x-icon" href="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=32" sizes="16x16" /> <link rel="apple-touch-icon" href="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=114" /> <link rel='openid.server' href='https://herbsutter.com/?openidserver=1' /> <link rel='openid.delegate' href='https://herbsutter.com/' /> <link rel="search" type="application/opensearchdescription+xml" href="https://herbsutter.com/osd.xml" title="Sutter’s Mill" /> <link rel="search" type="application/opensearchdescription+xml" href="https://s1.wp.com/opensearch.xml" title="WordPress.com" /> <style type="text/css"> .recentcomments a { display: inline !important; padding: 0 !important; margin: 0 !important; } table.recentcommentsavatartop img.avatar, table.recentcommentsavatarend img.avatar { border: 0px; margin: 0; } table.recentcommentsavatartop a, table.recentcommentsavatarend a { border: 0px !important; background-color: transparent !important; } td.recentcommentsavatarend, td.recentcommentsavatartop { padding: 0px 0px 1px 0px; margin: 0px; } td.recentcommentstextend { border: none !important; padding: 0px 0px 2px 10px; } .rtl td.recentcommentstextend { padding: 0px 10px 2px 0px; } td.recentcommentstexttop { border: none; padding: 0px 0px 0px 10px; } .rtl td.recentcommentstexttop { padding: 0px 10px 0px 0px; } </style> <meta name="description" content="4 posts published by Herb Sutter during December 2013" /> </head> <body class="archive date wp-embed-responsive customizer-styles-applied has-sidebar jetpack-reblog-enabled categories-hidden tags-hidden"> <div id="page" class="hfeed site"> <a class="skip-link screen-reader-text" href="#content">Skip to content</a> <div id="hero-header" class="site-hero-section"> <header id="masthead" class="site-header" role="banner"> <div class="inner"> <div class="site-branding"> <a class="site-logo-link" href="https://herbsutter.com/"> <img alt='' src='https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=80&d=identicon&r=G' srcset='https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=80&d=identicon&r=G 1x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=120&d=identicon&r=G 1.5x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=160&d=identicon&r=G 2x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=240&d=identicon&r=G 3x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=320&d=identicon&r=G 4x' class='avatar avatar-80 site-logo-image' height='80' width='80' loading='eager' decoding='async' /> </a><!-- .site-logo-link --> <p class="site-title"><a href="https://herbsutter.com/" rel="home">Sutter’s Mill</a></p> <p class="site-description">Herb Sutter on software development</p> </div><!-- .site-branding --> </div><!-- .inner --> </header><!-- #masthead --> </div> <div id="content-wrapper" class="content-wrapper"> <div id="content" class="site-content"> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <header class="page-header"> <h1 class="page-title">Month: <span>December 2013</span></h1> </header><!-- .page-header --> <article id="post-2387" class="post-2387 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/12/31/gotw-7c-minimizing-compile-time-dependencies-part-3/" rel="bookmark">GotW #7c: Minimizing Compile-Time Dependencies, Part 3</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p><span style="color:#5a5a5a;"><em>Now the unnecessary headers have been removed, and avoidable dependencies on the internals of the class have been eliminated. Is there any further decoupling that can be done? The answer takes us back to basic principles of solid class design.<br /> </em></span></p> <p> </p> <h1>Problem<br /> </h1> <h2>JG Question<br /> </h2> <p>1. What is the tightest coupling you can express in C++? And what’s the second-tightest? </p> <h2>Guru Question<br /> </h2> <p>2. The Incredible Shrinking Header has now been greatly trimmed, but there may still be ways to reduce the dependencies further. What further <span style="color:#2e74b5;">#include</span>s could be removed if we made further changes to <span style="color:#2e74b5;">X</span>, and how? </p> <p>This time, you may make any changes at all to <span style="color:#2e74b5;">X</span> as long as they don’t change its public interface, so that existing code that uses <span style="color:#2e74b5;">X</span> is unaffected. Again, note that the comments are important. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// x.h: after converting to use a Pimpl to hide implementation details<br />//<br />#include <iosfwd><br />#include <memory><br />#include "a.h" // class A (has virtual functions)<br />#include "b.h" // class B (has no virtual functions)<br />class C;<br />class E;<br /><br />class X : public A, private B {<br />public:<br /> X( const C& );<br /> B f( int, char* );<br /> C f( int, C );<br /> C& g( B );<br /> E h( E );<br /> virtual std::ostream& print( std::ostream& ) const;<br /><br />private:<br /> struct impl;<br /> std::unique_ptr<impl> pimpl; // ptr to a forward-declared class<br />};<br /><br />std::ostream& operator<<( std::ostream& os, const X& x ) {<br /> return x.print(os);<br />} </code></pre></p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/12/31/gotw-7c-minimizing-compile-time-dependencies-part-3/#comments">14 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/12/31/gotw-7c-minimizing-compile-time-dependencies-part-3/" rel="bookmark"><time class="entry-date published updated" datetime="2013-12-31T12:32:15-08:00">2013-12-31</time></a> </span> <span class="word-count">1 Minute</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2384" class="post-2384 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/12/31/gotw-7b-solution-minimizing-compile-time-dependencies-part-2/" rel="bookmark">GotW #7b Solution: Minimizing Compile-Time Dependencies, Part 2</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p><span style="color:#5a5a5a;"><em>Now that the unnecessary headers have been removed, it’s time for Phase 2: How can you limit dependencies on the internals of a class?<br /> </em></span></p> <p> </p> <h1>Problem<br /> </h1> <h2>JG Questions<br /> </h2> <p>1. What does <span style="color:#2e74b5;">private</span> mean for a class member in C++? </p> <p>2. Why does changing the private members of a type cause a recompilation? </p> <h2>Guru Question<br /> </h2> <p>3. Below is how the header from the previous Item looks after the initial cleanup pass. What further <span style="color:#2e74b5;">#include</span>s could be removed if we made some suitable changes, and how? </p> <p>This time, you may make changes to <span style="color:#2e74b5;">X</span> as long as <span style="color:#2e74b5;">X</span>‘s base classes and its public interface remain unchanged; any current code that already uses <span style="color:#2e74b5;">X</span> should not be affected beyond requiring a simple recompilation. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// x.h: sans gratuitous headers<br />//<br />#include <iosfwd><br />#include <list><br /><br />// None of A, B, C, or D are templates.<br />// Only A and C have virtual functions.<br />#include "a.h" // class A<br />#include "b.h" // class B<br />#include "c.h" // class C<br />#include "d.h" // class D<br />class E;<br /><br />class X : public A, private B {<br />public:<br /> X( const C& );<br /> B f( int, char* );<br /> C f( int, C );<br /> C& g( B );<br /> E h( E );<br /> virtual std::ostream& print( std::ostream& ) const;<br /><br /> private:<br /> std::list<C> clist;<br /> D d;<br />};<br /><br />std::ostream& operator<<( std::ostream& os, const X& x ) {<br /> return x.print(os);<br />} </code></pre> </p> <p> </p> <h1>Solution<br /> </h1> <h2>1. What does private mean for a class member in C++?<br /> </h2> <p>It means that outside code cannot access that member. Specifically, it cannot name it or call it. </p> <p>For example, given this class: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>class widget {<br />public:<br /> void f() { }<br />private:<br /> void f(int) { }<br /> int i;<br />}; </code></pre> </p> <p>Outside code cannot use the name of the <span style="color:#2e74b5;">private</span> members: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> int main() {<br /> auto w = widget{};<br /> w.f(); // ok<br /> w.f(42); // error, cannot access name "f(int)"<br /> w.i = 42; // error, cannot access name "i"<br />} </code></pre> </p> <p> </p> <h2>2. Why does changing the private members of a type cause a recompilation?<br /> </h2> <p>Because private data members can change the size of the object, and private member functions participate in overload resolution. </p> <p>Note that accessibility is still safely enforced: <em>Calling code</em> still doesn’t get to use the private parts of the class. However, <em>the compiler</em> gets to know all about them at all times, including as it compiles the calling code. This does increase build coupling, but it’s for a deliberate reason: C++ has always been designed for efficiency, and a little-appreciated cornerstone of that is that C++ is designed to by default expose a type’s full implementation to the compiler in order to make aggressive optimization easier. It’s one of the fundamental reasons C++ is an efficient language. </p> <p> </p> <h2>3. What further #includes could be removed if we made some suitable changes, and how? … any current code that already uses X should not be affected beyond requiring a simple recompilation.<br /> </h2> <p>There are a few things we weren’t able to do in the previous problem: </p> <ul> <li>We had to leave <span style="color:#2e74b5;">a.h</span> and <span style="color:#2e74b5;">b.h</span>. We couldn’t get rid of these because <span style="color:#2e74b5;">X</span> inherits from both <span style="color:#2e74b5;">A</span> and <span style="color:#2e74b5;">B</span>, and you always have to have full definitions for base classes so that the compiler can determine <span style="color:#2e74b5;">X</span>‘s object size, virtual functions, and other fundamentals. (Can you anticipate how to remove one of these? Think about it: Which one can you remove, and why/how? The answer will come shortly.) </li> <li>We had to leave <span style="color:#2e74b5;">list</span>, <span style="color:#2e74b5;">c.h</span> and <span style="color:#2e74b5;">d.h</span>. We couldn’t get rid of these right away because a <span style="color:#2e74b5;">list<C></span> and a <span style="color:#2e74b5;">D</span> appear as private data members of <span style="color:#2e74b5;">X</span>. Although <span style="color:#2e74b5;">C</span> appears as neither a base class nor a member, it is being used to instantiate the <span style="color:#2e74b5;">list</span> member, and some have compilers required that when you instantiate <span style="color:#2e74b5;">list<C></span> you be able to see the definition of <span style="color:#2e74b5;">C</span>. (The standard doesn’t require a definition here, though, so even if the compiler you are currently using has this restriction, you can expect the restriction to go away over time.) </li> </ul> <p>Now let’s talk about the beauty of Pimpls. </p> <p> </p> <h3>The Pimpl Idiom<br /> </h3> <p>C++ lets us easily encapsulate the private parts of a class from unauthorized access. Unfortunately, because of the header file approach inherited from C, it can take a little more work to encapsulate dependencies on a class’ privates. </p> <p>“But,” you say, “the whole point of encapsulation is that the client code shouldn’t have to know or care about a class’ private implementation details, right?” Right, and in C++ the client code doesn’t need to know or care about access to a class’ privates (because unless it’s a friend it isn’t allowed any), but because the privates are visible in the header the client code does have to depend upon any types they mention. This coupling between the caller and the class’s internal details creates dependencies on both (re)compilation and binary layout. </p> <p>How can we better insulate clients from a class’ private implementation details? One good way is to use a special form of the handle/body idiom, popularly called the Pimpl Idiom because of the intentionally pronounceable <span style="color:#2e74b5;">pimpl</span> pointer, as a compilation firewall. </p> <p>A Pimpl is just an opaque pointer (a pointer to a forward-declared, but undefined, helper class) used to hide the private members of a class. That is, instead of writing this: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// file widget.h<br />//<br />class widget {<br /> // public and protected members<br />private:<br /> // private members; whenever these change,<br /> // all client code must be recompiled<br />}; </code></pre> </p> <p>We write instead: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// file widget.h<br />//<br />#include <memory><br /><br />class widget {<br />public:<br /> widget();<br /> ~widget();<br /> // public and protected members<br />private:<br /> struct impl;<br /> std::unique_ptr<impl> pimpl; // ptr to a forward-declared class<br />};<br /><br />// file widget.cpp<br />//<br />#include "widget.h"<br /><br />struct widget::impl {<br /> // private members; fully hidden, can be<br /> // changed at will without recompiling clients<br />};<br /><br />widget::widget() : pimpl{ make_unique<widget::impl>(/*...*/) } { }<br />widget::~widget() =default; </code></pre> </p> <p>Every <span style="color:#2e74b5;">widget</span> object dynamically allocates its <span style="color:#2e74b5;">impl</span> object. If you think of an object as a physical block, we’ve essentially lopped off a large chunk of the block and in its place left only “a little bump on the side”—the opaque pointer, or Pimpl. If copy and move are appropriate for your type, write those four operations to perform a deep copy that clones the <span style="color:#2e74b5;">impl</span> state. </p> <p>The major advantages of this idiom come from the fact that it breaks the caller’s dependency on the private details, including breaking both compile-time dependencies and binary dependencies: </p> <ul> <li>Types mentioned only in a class’ implementation need no longer be defined for client code, which can eliminate extra <span style="color:#2e74b5;">#include</span>s and improve compile speeds. </li> <li>A class’ implementation can be changed—that is, private members can be freely added or removed—without recompiling client code. This is a useful technique for providing ABI-safety or binary compatibility, so that the client code is not dependent on the exact layout of the object. </li> </ul> <p>The major costs of this idiom are in performance: </p> <ul> <li>Each construction/destruction must allocate/deallocate memory. </li> <li>Each access of a hidden member can require at least one extra indirection. (If the hidden member being accessed itself uses a back pointer to call a function in the visible class, there will be multiple indirections, but is usually easy to avoid needing a back pointer.) </li> </ul> <p>And of course we’re replacing any removed headers with the <span style="color:#2e74b5;"><memory></span> header. </p> <p>We’ll come back to these and other Pimpl issues in GotW #24. For now, in our example, there were three headers whose definitions were needed simply because they appeared as private members of <span style="color:#2e74b5;">X</span>. If we instead restructure <span style="color:#2e74b5;">X</span> to use a Pimpl, we can immediately make several further simplifications: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>#include <list><br />#include "c.h" // class C<br />#include "d.h" // class D </code></pre> </p> <p>One of these headers (<span style="color:#2e74b5;">c.h</span>) can be replaced with a forward declaration because <span style="color:#2e74b5;">C</span> is still being mentioned elsewhere as a parameter or return type, and the other two (<span style="color:#2e74b5;">list</span> and <span style="color:#2e74b5;">d.h</span>) can disappear completely. </p> <blockquote> <p><strong>Guideline:</strong> For widely-included classes whose implementations may change, or to provide ABI-safety or binary compatibility, consider using the compiler-firewall idiom (Pimpl Idiom) to hide implementation details. Use an opaque pointer (a pointer to a declared but undefined class) declared as <strong>struct impl; std::unique_ptr<impl> pimpl;</strong> to store private nonvirtual members. </p> </blockquote> <p> </p> <p>Note: We can’t tell from the original code by itself whether or not <span style="color:#2e74b5;">X</span> had (default) copy or move operations. If it did, then to preserve that we would need to write them again ourselves since the move-only <span style="color:#2e74b5;">unique_ptr</span> member suppresses the implicit generation of copy construction and copy assignment, and the user-declared destructor suppresses the implicit generation of move construction and move assignment. If we do need to write them by hand, the move constructor and move assignment can be <span style="color:#2e74b5;">=default</span>ed, and the copy constructor and copy assignment will need to copy the Pimpl object. </p> <p>After making that additional change, the header looks like this: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// x.h: after converting to use a Pimpl<br />//<br />#include <iosfwd><br />#include <memory><br />#include "a.h" // class A (has virtual functions)<br />#include "b.h" // class B (has no virtual functions)<br />class C;<br />class E;<br /><br />class X : public A, private B {<br />public:<br /> ~X(); // defined out of line<br /> // and copy/move operations if X had them before<br /><br /> X( const C& );<br /> B f( int, char* );<br /> C f( int, C );<br /> C& g( B );<br /> E h( E );<br /> virtual std::ostream& print( std::ostream& ) const;<br /><br />private:<br /> struct impl;<br /> std::unique_ptr<impl> pimpl; // ptr to a forward-declared class<br />};<br /><br />std::ostream& operator<<( std::ostream& os, const X& x ) {<br /> return x.print(os);<br />} </code></pre> </p> <p>Without more extensive changes, we still need the definitions for <span style="color:#2e74b5;">A</span> and <span style="color:#2e74b5;">B</span> because they are base classes, and we have to know at least their sizes in order to define the derived class <span style="color:#2e74b5;">X</span>. </p> <p>The private details go into <span style="color:#2e74b5;">X</span>‘s implementation file where client code never sees them and therefore never depends upon them: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Implementation file x.cpp<br />//<br />#include <list><br />#include "c.h" // class C<br />#include "d.h" // class D<br />using namespace std;<br /><br />struct X::impl {<br /> list<C> clist;<br /> D d;<br />};<br /><br />X::X() : pimpl{ make_unique<X::impl>(/*...*/) } { }<br />X::~X() =default; </code></pre> </p> <p>That brings us down to including only four headers, which is a great improvement—but it turns out that there is still a little more we could do, if only we were allowed to change the structure of <span style="color:#2e74b5;">X</span> more extensively. This leads us nicely into Part 3… </p> <p> </p> <h2>Acknowledgments<br /> </h2> <p>Thanks to the following for their feedback to improve this article: John Humphrey, thokra, Motti Lanzkron, Marcelo Pinto.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/12/31/gotw-7b-solution-minimizing-compile-time-dependencies-part-2/#comments">14 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/12/31/gotw-7b-solution-minimizing-compile-time-dependencies-part-2/" rel="bookmark"><time class="entry-date published" datetime="2013-12-31T12:24:37-08:00">2013-12-31</time><time class="updated" datetime="2014-01-03T09:46:25-08:00">2014-01-03</time></a> </span> <span class="word-count">7 Minutes</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2375" class="post-2375 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/12/09/grace-hopper-on-letterman-1986/" rel="bookmark">Grace Hopper on Letterman, 1986</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p>Google’s doodle today reminded me of Grace Hopper’s amazing contributions.</p> <p>I enjoyed this 10-minute video, and you might as well: <a href="https://www.youtube.com/watch?v=1-vcErOPofQ">Grace Hopper on Letterman in 1986</a> on the occasion of her (final) retirement.</p> <p>It’s not deep, but especially in the second half Amazing Grace demonstrates how to talk to a non-specialist audience. Good reminders for all of us who speak Geek Jargon a little too fluently!</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/12/09/grace-hopper-on-letterman-1986/#comments">2 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/12/09/grace-hopper-on-letterman-1986/" rel="bookmark"><time class="entry-date published updated" datetime="2013-12-09T11:13:55-08:00">2013-12-09</time></a> </span> <span class="word-count">1 Minute</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2367" class="post-2367 post type-post status-publish format-standard hentry category-concurrency"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/12/05/reader-qa-book-recommendations/" rel="bookmark">Reader Q&A: Book recommendations</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p>Vigen Isayan emailed me today to ask:</p> <blockquote><p>What book(s) you would recommend for learning</p> <p>1. design patterns, and</p> <p>2. concurrency programming.</p></blockquote> <p>Off the top of my head:</p> <p>1. For Design Patterns, the greatest is still the original <a href="http://en.wikipedia.org/wiki/Design_Patterns">“Gang of Four” Design Patterns book</a>. The design patterns are mostly universal, and the implementations happen to focus on OO techniques (dynamic run-time virtual dispatch etc.) but you can also express many of the patterns using generic programming (static compile-time templates etc.) – for example <a href="http://www.drdobbs.com/cpp/generalizing-observer/184403873?queryText=sutter%2B%2522generalizing%2Bobserver%2522">Observer</a> becomes really simple. The book is almost two decades old, has inspired huge numbers of follow-on patterns books, and there’s still none better of its kind that I know of.</p> <p>2. For concurrency (and parallelism), check out my <a href="https://herbsutter.com/2010/09/24/effective-concurrency-know-when-to-use-an-active-object-instead-of-a-mutex/">33 articles on Effective Concurrency</a>. I hope to assemble them into a book in the near future. In the meantime they’re all out there online freely available.</p> <p>If you have additional recommendations, please post them in the comments. Thanks.</p> <h3>On a personal note</h3> <p>Speaking of the Gang of Four, here’s a personal story I don’t know if I’ve shared on the blog before:</p> <p>At the time it first came out, I was working in downtown Toronto. We had a really excellent local bookstore that specialized in programming books and magazines (alas, it’s long gone now). On lunch breaks, I would go there to browse and get new books to absorb. Note that this was before I was a published author myself, and I had no idea about major new books coming out, so I had no warning of what was about to happen.</p> <p>On one day that at first seemed like any other, at lunchtime I was browsing the shelves as usual, and I saw copies of a white and blue hardcover book I’d never seen before. Curious, I picked up a copy. It had an unusual title, <em>Design Patterns</em>. I had never heard of the book or its authors before, knew nothing about it at all, and so was quite unsuspecting when I opened it and something happened that I had never experienced before and haven’t experienced since (so far):</p> <p>I opened that book for the first time, stood there paging through it for less than five minutes, <em>and knew immediately and profoundly that I was holding a classic in my hands</em>. The realization was so unexpected and surprising, it hit me almost physically. At first sight, it was as easy to recognize this book as an important leap forward as the first you see an airplane flying in the sky. Scales fell from my eyes: Cataloguing OO design problems and their known solutions! Imagine!</p> <p>I had already learned a few of the patterns on my own here and there, some through hard work and experience, others by combining ideas from various articles, many by working with experienced colleagues. But suddenly I found myself standing there in the bookstore aisle just absorbing one problem and solution after another after another, and feeling my understanding begin expanding. Even the patterns I sort of knew about were explained with concise clarity: Motivation, the problem <em>and the specific constraints on the solution</em> which are so important because they affect the design. Known solutions. Variations with tradeoffs.</p> <p>Bliss! No, more than bliss — treasure.</p> <p>This must be what explorers and hunters feel like when one day unexpectedly they discover an unopened and unransacked tomb of a young Egyptian Pharaoh, a sunken treasure galleon filled with precious cargo and artifacts, or a cave near the West Bank containing well-preserved two-thousand-year-old scrolls of important literature.</p> <p>And <em>Design Patterns</em> was language-agnostic, to boot.</p> <p>Nineteen years later, it’s still at the top of my list of design books to recommend.</p> <p>Disclaimer: Something this profound inspires a whole new subculture. Later “pattern” wannabe books often went way, way, <em>way</em> overboard, some of them almost to the border of quasi-mysticism. Ignore most (not all, but most) of the follow-on pattern books. Only a few are worth your time; read the reviews carefully first.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/concurrency/" rel="category tag">Concurrency</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/12/05/reader-qa-book-recommendations/#comments">8 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/12/05/reader-qa-book-recommendations/" rel="bookmark"><time class="entry-date published" datetime="2013-12-05T15:31:01-08:00">2013-12-05</time><time class="updated" datetime="2013-12-05T16:14:43-08:00">2013-12-05</time></a> </span> <span class="word-count">3 Minutes</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> </main><!-- #main --> </div><!-- #primary --> <div id="secondary" class="widget-area" role="complementary"> <aside id="search-4" class="widget widget_search"><form role="search" method="get" class="search-form" action="https://herbsutter.com/"> <label> <span class="screen-reader-text">Search for:</span> <input type="search" class="search-field" placeholder="Search …" value="" name="s" /> </label> <input type="submit" class="search-submit" value="Search" /> </form></aside><aside id="blog_subscription-3" class="widget widget_blog_subscription jetpack_subscription_widget"><h1 class="widget-title"><label for="subscribe-field">Follow by email</label></h1> <div class="wp-block-jetpack-subscriptions__container"> <form action="https://subscribe.wordpress.com" method="post" accept-charset="utf-8" data-blog="3379246" data-post_access_level="everybody" id="subscribe-blog" > <p id="subscribe-email"> <label id="subscribe-field-label" for="subscribe-field" class="screen-reader-text" > Email Address: </label> <input type="email" name="email" style="width: 95%; padding: 1px 10px" placeholder="Email Address" value="" id="subscribe-field" required /> </p> <p id="subscribe-submit" > <input type="hidden" name="action" value="subscribe"/> <input type="hidden" name="blog_id" value="3379246"/> <input type="hidden" name="source" value="https://herbsutter.com/2013/12/"/> <input type="hidden" name="sub-type" value="widget"/> <input type="hidden" name="redirect_fragment" value="subscribe-blog"/> <input type="hidden" id="_wpnonce" name="_wpnonce" value="19c10c9de2" /> <button type="submit" class="wp-block-button__link" > Subscribe </button> </p> </form> </div> </aside><aside id="block-2" class="widget widget_block widget_media_image"> <figure class="wp-block-image size-medium is-resized is-style-default"><a href="https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg"><img loading="lazy" width="300" height="230" src="https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=300" alt="" class="wp-image-5065" style="width:248px;height:auto" srcset="https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=300 300w, https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=600 600w, https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=150 150w" sizes="(max-width: 300px) 100vw, 300px" /></a></figure> </aside><aside id="block-3" class="widget widget_block widget_text"> <p class="has-small-font-size">I'm an author and speaker, and a programming language nerd whose focus is on enabling our program code to be both clean <em>and</em> fast. I've been writing about programming since 1993, usually about C++ or about concurrency and parallelism. I'm the designer or co-designer of a number of standardized ISO C++ language and library features. I've served as the chair of the <a href="https://isocpp.org/std/the-committee">ISO C++ standards committee</a> since 2002, and as the chair of the <a href="https://isocpp.org/about">Standard C++ Foundation</a> since 2012. I'm a technical fellow at <a href="https://www.citadelsecurities.com/">Citadel Securities</a>. This personal website expresses the opinions of none of those organizations.</p> </aside><aside id="archives-4" class="widget widget_archive"><h1 class="widget-title">Archives</h1> <ul> <li><a href='https://herbsutter.com/2025/02/'>February 2025</a> (1)</li> <li><a href='https://herbsutter.com/2025/01/'>January 2025</a> (5)</li> <li><a href='https://herbsutter.com/2024/12/'>December 2024</a> (1)</li> <li><a href='https://herbsutter.com/2024/11/'>November 2024</a> (2)</li> <li><a href='https://herbsutter.com/2024/10/'>October 2024</a> (3)</li> <li><a href='https://herbsutter.com/2024/09/'>September 2024</a> (2)</li> <li><a href='https://herbsutter.com/2024/08/'>August 2024</a> (1)</li> <li><a href='https://herbsutter.com/2024/07/'>July 2024</a> (2)</li> <li><a href='https://herbsutter.com/2024/06/'>June 2024</a> (2)</li> <li><a href='https://herbsutter.com/2024/04/'>April 2024</a> (1)</li> <li><a href='https://herbsutter.com/2024/03/'>March 2024</a> (3)</li> <li><a href='https://herbsutter.com/2024/02/'>February 2024</a> (1)</li> <li><a href='https://herbsutter.com/2023/11/'>November 2023</a> (1)</li> <li><a href='https://herbsutter.com/2023/10/'>October 2023</a> (1)</li> <li><a href='https://herbsutter.com/2023/09/'>September 2023</a> (1)</li> <li><a href='https://herbsutter.com/2023/08/'>August 2023</a> (1)</li> <li><a href='https://herbsutter.com/2023/06/'>June 2023</a> (1)</li> <li><a href='https://herbsutter.com/2023/04/'>April 2023</a> (2)</li> <li><a href='https://herbsutter.com/2023/02/'>February 2023</a> (1)</li> <li><a href='https://herbsutter.com/2022/12/'>December 2022</a> (1)</li> <li><a href='https://herbsutter.com/2022/11/'>November 2022</a> (1)</li> <li><a href='https://herbsutter.com/2022/10/'>October 2022</a> (2)</li> <li><a href='https://herbsutter.com/2022/09/'>September 2022</a> (2)</li> <li><a href='https://herbsutter.com/2021/10/'>October 2021</a> (1)</li> <li><a href='https://herbsutter.com/2021/06/'>June 2021</a> (2)</li> <li><a href='https://herbsutter.com/2021/05/'>May 2021</a> (1)</li> <li><a href='https://herbsutter.com/2021/03/'>March 2021</a> (2)</li> <li><a href='https://herbsutter.com/2021/02/'>February 2021</a> (4)</li> <li><a href='https://herbsutter.com/2021/01/'>January 2021</a> (5)</li> <li><a href='https://herbsutter.com/2020/12/'>December 2020</a> (1)</li> <li><a href='https://herbsutter.com/2020/11/'>November 2020</a> (2)</li> <li><a href='https://herbsutter.com/2020/10/'>October 2020</a> (1)</li> <li><a href='https://herbsutter.com/2020/09/'>September 2020</a> (2)</li> <li><a href='https://herbsutter.com/2020/07/'>July 2020</a> (1)</li> <li><a href='https://herbsutter.com/2020/06/'>June 2020</a> (2)</li> <li><a href='https://herbsutter.com/2020/05/'>May 2020</a> (3)</li> <li><a href='https://herbsutter.com/2020/04/'>April 2020</a> (1)</li> <li><a href='https://herbsutter.com/2020/03/'>March 2020</a> (1)</li> <li><a href='https://herbsutter.com/2020/02/'>February 2020</a> (4)</li> <li><a href='https://herbsutter.com/2019/11/'>November 2019</a> (1)</li> <li><a href='https://herbsutter.com/2019/10/'>October 2019</a> (1)</li> <li><a href='https://herbsutter.com/2019/09/'>September 2019</a> (4)</li> <li><a href='https://herbsutter.com/2019/07/'>July 2019</a> (5)</li> <li><a href='https://herbsutter.com/2019/06/'>June 2019</a> (1)</li> <li><a href='https://herbsutter.com/2019/05/'>May 2019</a> (1)</li> <li><a href='https://herbsutter.com/2019/04/'>April 2019</a> (1)</li> <li><a href='https://herbsutter.com/2019/02/'>February 2019</a> (1)</li> <li><a href='https://herbsutter.com/2018/11/'>November 2018</a> (2)</li> <li><a href='https://herbsutter.com/2018/09/'>September 2018</a> (3)</li> <li><a href='https://herbsutter.com/2018/07/'>July 2018</a> (1)</li> <li><a href='https://herbsutter.com/2018/04/'>April 2018</a> (1)</li> <li><a href='https://herbsutter.com/2017/11/'>November 2017</a> (2)</li> <li><a href='https://herbsutter.com/2017/10/'>October 2017</a> (3)</li> <li><a href='https://herbsutter.com/2017/09/'>September 2017</a> (3)</li> <li><a href='https://herbsutter.com/2017/07/'>July 2017</a> (2)</li> <li><a href='https://herbsutter.com/2017/06/'>June 2017</a> (1)</li> <li><a href='https://herbsutter.com/2017/03/'>March 2017</a> (1)</li> <li><a href='https://herbsutter.com/2017/02/'>February 2017</a> (2)</li> <li><a href='https://herbsutter.com/2016/11/'>November 2016</a> (1)</li> <li><a href='https://herbsutter.com/2016/09/'>September 2016</a> (4)</li> <li><a href='https://herbsutter.com/2016/06/'>June 2016</a> (2)</li> <li><a href='https://herbsutter.com/2016/03/'>March 2016</a> (1)</li> <li><a href='https://herbsutter.com/2015/10/'>October 2015</a> (1)</li> <li><a href='https://herbsutter.com/2015/09/'>September 2015</a> (1)</li> <li><a href='https://herbsutter.com/2015/07/'>July 2015</a> (1)</li> <li><a href='https://herbsutter.com/2015/06/'>June 2015</a> (1)</li> <li><a href='https://herbsutter.com/2015/05/'>May 2015</a> (1)</li> <li><a href='https://herbsutter.com/2015/04/'>April 2015</a> (1)</li> <li><a href='https://herbsutter.com/2015/01/'>January 2015</a> (1)</li> <li><a href='https://herbsutter.com/2014/12/'>December 2014</a> (1)</li> <li><a href='https://herbsutter.com/2014/11/'>November 2014</a> (3)</li> <li><a href='https://herbsutter.com/2014/10/'>October 2014</a> (2)</li> <li><a href='https://herbsutter.com/2014/09/'>September 2014</a> (2)</li> <li><a href='https://herbsutter.com/2014/08/'>August 2014</a> (1)</li> <li><a href='https://herbsutter.com/2014/07/'>July 2014</a> (2)</li> <li><a href='https://herbsutter.com/2014/05/'>May 2014</a> (3)</li> <li><a href='https://herbsutter.com/2014/04/'>April 2014</a> (4)</li> <li><a href='https://herbsutter.com/2014/03/'>March 2014</a> (4)</li> <li><a href='https://herbsutter.com/2014/02/'>February 2014</a> (2)</li> <li><a href='https://herbsutter.com/2014/01/'>January 2014</a> (4)</li> <li><a href='https://herbsutter.com/2013/12/' aria-current="page">December 2013</a> (4)</li> <li><a href='https://herbsutter.com/2013/11/'>November 2013</a> (4)</li> <li><a href='https://herbsutter.com/2013/10/'>October 2013</a> (2)</li> <li><a href='https://herbsutter.com/2013/09/'>September 2013</a> (6)</li> <li><a href='https://herbsutter.com/2013/08/'>August 2013</a> (5)</li> <li><a href='https://herbsutter.com/2013/07/'>July 2013</a> (1)</li> <li><a href='https://herbsutter.com/2013/06/'>June 2013</a> (7)</li> <li><a href='https://herbsutter.com/2013/05/'>May 2013</a> (22)</li> <li><a href='https://herbsutter.com/2013/04/'>April 2013</a> (2)</li> <li><a href='https://herbsutter.com/2013/03/'>March 2013</a> (1)</li> <li><a href='https://herbsutter.com/2013/02/'>February 2013</a> (1)</li> <li><a href='https://herbsutter.com/2013/01/'>January 2013</a> (3)</li> <li><a href='https://herbsutter.com/2012/12/'>December 2012</a> (3)</li> <li><a href='https://herbsutter.com/2012/11/'>November 2012</a> (6)</li> <li><a href='https://herbsutter.com/2012/10/'>October 2012</a> (5)</li> <li><a href='https://herbsutter.com/2012/09/'>September 2012</a> (3)</li> <li><a href='https://herbsutter.com/2012/08/'>August 2012</a> (3)</li> <li><a href='https://herbsutter.com/2012/07/'>July 2012</a> (1)</li> <li><a href='https://herbsutter.com/2012/06/'>June 2012</a> (7)</li> <li><a href='https://herbsutter.com/2012/05/'>May 2012</a> (5)</li> <li><a href='https://herbsutter.com/2012/04/'>April 2012</a> (17)</li> <li><a href='https://herbsutter.com/2012/03/'>March 2012</a> (4)</li> <li><a href='https://herbsutter.com/2012/02/'>February 2012</a> (5)</li> <li><a href='https://herbsutter.com/2012/01/'>January 2012</a> (7)</li> <li><a href='https://herbsutter.com/2011/12/'>December 2011</a> (3)</li> <li><a href='https://herbsutter.com/2011/11/'>November 2011</a> (6)</li> <li><a href='https://herbsutter.com/2011/10/'>October 2011</a> (10)</li> <li><a href='https://herbsutter.com/2011/09/'>September 2011</a> (3)</li> <li><a href='https://herbsutter.com/2011/08/'>August 2011</a> (3)</li> <li><a href='https://herbsutter.com/2011/07/'>July 2011</a> (2)</li> <li><a href='https://herbsutter.com/2011/06/'>June 2011</a> (4)</li> <li><a href='https://herbsutter.com/2011/05/'>May 2011</a> (5)</li> <li><a href='https://herbsutter.com/2011/04/'>April 2011</a> (3)</li> <li><a href='https://herbsutter.com/2011/03/'>March 2011</a> (2)</li> <li><a href='https://herbsutter.com/2011/01/'>January 2011</a> (1)</li> <li><a href='https://herbsutter.com/2010/12/'>December 2010</a> (2)</li> <li><a href='https://herbsutter.com/2010/10/'>October 2010</a> (5)</li> <li><a href='https://herbsutter.com/2010/09/'>September 2010</a> (3)</li> <li><a href='https://herbsutter.com/2010/08/'>August 2010</a> (2)</li> <li><a href='https://herbsutter.com/2010/07/'>July 2010</a> (1)</li> <li><a href='https://herbsutter.com/2010/06/'>June 2010</a> (2)</li> <li><a href='https://herbsutter.com/2010/05/'>May 2010</a> (5)</li> <li><a href='https://herbsutter.com/2010/04/'>April 2010</a> (5)</li> <li><a href='https://herbsutter.com/2010/03/'>March 2010</a> (9)</li> <li><a href='https://herbsutter.com/2010/02/'>February 2010</a> (2)</li> <li><a href='https://herbsutter.com/2010/01/'>January 2010</a> (3)</li> <li><a href='https://herbsutter.com/2009/12/'>December 2009</a> (1)</li> <li><a href='https://herbsutter.com/2009/11/'>November 2009</a> (4)</li> <li><a href='https://herbsutter.com/2009/10/'>October 2009</a> (6)</li> <li><a href='https://herbsutter.com/2009/09/'>September 2009</a> (2)</li> <li><a href='https://herbsutter.com/2009/08/'>August 2009</a> (2)</li> <li><a href='https://herbsutter.com/2009/07/'>July 2009</a> (2)</li> <li><a href='https://herbsutter.com/2009/06/'>June 2009</a> (3)</li> <li><a href='https://herbsutter.com/2009/05/'>May 2009</a> (4)</li> <li><a href='https://herbsutter.com/2009/04/'>April 2009</a> (2)</li> <li><a href='https://herbsutter.com/2009/03/'>March 2009</a> (4)</li> <li><a href='https://herbsutter.com/2009/02/'>February 2009</a> (3)</li> <li><a href='https://herbsutter.com/2009/01/'>January 2009</a> (5)</li> <li><a href='https://herbsutter.com/2008/12/'>December 2008</a> (4)</li> <li><a href='https://herbsutter.com/2008/11/'>November 2008</a> (2)</li> <li><a href='https://herbsutter.com/2008/10/'>October 2008</a> (3)</li> <li><a href='https://herbsutter.com/2008/09/'>September 2008</a> (3)</li> <li><a href='https://herbsutter.com/2008/08/'>August 2008</a> (4)</li> <li><a href='https://herbsutter.com/2008/07/'>July 2008</a> (6)</li> <li><a href='https://herbsutter.com/2008/06/'>June 2008</a> (6)</li> <li><a href='https://herbsutter.com/2008/05/'>May 2008</a> (2)</li> <li><a href='https://herbsutter.com/2008/04/'>April 2008</a> (6)</li> <li><a href='https://herbsutter.com/2008/03/'>March 2008</a> (5)</li> <li><a href='https://herbsutter.com/2008/02/'>February 2008</a> (1)</li> <li><a href='https://herbsutter.com/2008/01/'>January 2008</a> (7)</li> <li><a href='https://herbsutter.com/2007/12/'>December 2007</a> (5)</li> <li><a href='https://herbsutter.com/2007/11/'>November 2007</a> (4)</li> <li><a href='https://herbsutter.com/2007/10/'>October 2007</a> (1)</li> <li><a href='https://herbsutter.com/2007/09/'>September 2007</a> (6)</li> <li><a href='https://herbsutter.com/2007/08/'>August 2007</a> (6)</li> <li><a href='https://herbsutter.com/2007/07/'>July 2007</a> (6)</li> <li><a href='https://herbsutter.com/2007/06/'>June 2007</a> (3)</li> <li><a href='https://herbsutter.com/2007/05/'>May 2007</a> (3)</li> <li><a href='https://herbsutter.com/2007/04/'>April 2007</a> (2)</li> <li><a href='https://herbsutter.com/2007/03/'>March 2007</a> (3)</li> <li><a href='https://herbsutter.com/2007/02/'>February 2007</a> (3)</li> <li><a href='https://herbsutter.com/2007/01/'>January 2007</a> (6)</li> <li><a href='https://herbsutter.com/2006/12/'>December 2006</a> (2)</li> </ul> </aside></div><!-- #secondary --> </div><!-- #content --> <footer id="colophon" class="site-footer" role="contentinfo"> <div class="site-info"> <a href="https://wordpress.com/?ref=footer_blog" rel="nofollow">Blog at WordPress.com.</a> </div><!-- .site-info --> </footer><!-- #colophon --> </div><!-- #content-wrapper --> </div><!-- #page --> <!-- --> <script type="text/javascript" src="//0.gravatar.com/js/hovercards/hovercards.min.js?ver=2025097d8bf6c02970a26c6b0c26b0fcfc89796aa30f84307cffd8fd28d2bcca53dd7a" id="grofiles-cards-js"></script> <script type="text/javascript" id="wpgroho-js-extra"> /* <![CDATA[ */ var WPGroHo = {"my_hash":""}; /* ]]> */ </script> <script crossorigin='anonymous' type='text/javascript' src='https://s2.wp.com/wp-content/mu-plugins/gravatar-hovercards/wpgroho.js?m=1610363240i'></script> <script> // Initialize and attach hovercards to all gravatars ( function() { function init() { if ( typeof Gravatar === 'undefined' ) { return; } if ( typeof Gravatar.init !== 'function' ) { return; } Gravatar.profile_cb = function ( hash, id ) { WPGroHo.syncProfileData( hash, id ); }; Gravatar.my_hash = WPGroHo.my_hash; Gravatar.init( 'body', '#wp-admin-bar-my-account', { i18n: { 'Edit your profile →': 'Edit your profile →', 'View profile →': 'View profile →', 'Contact': 'Contact', 'Send money': 'Send money', 'Sorry, we are unable to load this Gravatar profile.': 'Sorry, we are unable to load this Gravatar profile.', 'Profile not found.': 'Profile not found.', 'Too Many Requests.': 'Too Many Requests.', 'Internal Server Error.': 'Internal Server Error.', }, } ); } if ( document.readyState !== 'loading' ) { init(); } else { document.addEventListener( 'DOMContentLoaded', init ); } } )(); </script> <div style="display:none"> <div class="grofile-hash-map-c0ba56bfd231f8f04feb057728975181"> </div> </div> <div id="actionbar" dir="ltr" style="display: none;" class="actnbr-pub-independent-publisher-2 actnbr-has-follow actnbr-has-actions"> <ul> <li class="actnbr-btn actnbr-hidden"> <a class="actnbr-action actnbr-actn-follow " href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path clip-rule="evenodd" d="m4 4.5h12v6.5h1.5v-6.5-1.5h-1.5-12-1.5v1.5 10.5c0 1.1046.89543 2 2 2h7v-1.5h-7c-.27614 0-.5-.2239-.5-.5zm10.5 2h-9v1.5h9zm-5 3h-4v1.5h4zm3.5 1.5h-1v1h1zm-1-1.5h-1.5v1.5 1 1.5h1.5 1 1.5v-1.5-1-1.5h-1.5zm-2.5 2.5h-4v1.5h4zm6.5 1.25h1.5v2.25h2.25v1.5h-2.25v2.25h-1.5v-2.25h-2.25v-1.5h2.25z" fill-rule="evenodd"></path></svg> <span>Subscribe</span> </a> <a class="actnbr-action actnbr-actn-following no-display" href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.5H4V15C4 15.2761 4.22386 15.5 4.5 15.5H11.5V17H4.5C3.39543 17 2.5 16.1046 2.5 15V4.5V3H4H16H17.5V4.5V12.5H16V4.5ZM5.5 6.5H14.5V8H5.5V6.5ZM5.5 9.5H9.5V11H5.5V9.5ZM12 11H13V12H12V11ZM10.5 9.5H12H13H14.5V11V12V13.5H13H12H10.5V12V11V9.5ZM5.5 12H9.5V13.5H5.5V12Z" fill="#008A20"></path><path class="following-icon-tick" d="M13.5 16L15.5 18L19 14.5" stroke="#008A20" stroke-width="1.5"></path></svg> <span>Subscribed</span> </a> <div class="actnbr-popover tip tip-top-left actnbr-notice" id="follow-bubble"> <div class="tip-arrow"></div> <div class="tip-inner actnbr-follow-bubble"> <ul> <li class="actnbr-sitename"> <a href="https://herbsutter.com"> <img loading='lazy' alt='' src='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png' srcset='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=75&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1.5x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=100&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 2x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=150&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 3x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=200&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 4x' class='avatar avatar-50' height='50' width='50' /> Sutter’s Mill </a> </li> <div class="actnbr-message no-display"></div> <form method="post" action="https://subscribe.wordpress.com" accept-charset="utf-8" style="display: none;"> <div class="actnbr-follow-count">Join 5,292 other subscribers</div> <div> <input type="email" name="email" placeholder="Enter your email address" class="actnbr-email-field" aria-label="Enter your email address" /> </div> <input type="hidden" name="action" value="subscribe" /> <input type="hidden" name="blog_id" value="3379246" /> <input type="hidden" name="source" value="https://herbsutter.com/2013/12/" /> <input type="hidden" name="sub-type" value="actionbar-follow" /> <input type="hidden" id="_wpnonce" name="_wpnonce" value="19c10c9de2" /> <div class="actnbr-button-wrap"> <button type="submit" value="Sign me up"> Sign me up </button> </div> </form> <li class="actnbr-login-nudge"> <div> Already have a WordPress.com account? <a href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Fherbsutter.com%252F2013%252F12%252F31%252Fgotw-7c-minimizing-compile-time-dependencies-part-3%252F">Log in now.</a> </div> </li> </ul> </div> </div> </li> <li class="actnbr-ellipsis actnbr-hidden"> <svg class="gridicon gridicons-ellipsis" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M7 12c0 1.104-.896 2-2 2s-2-.896-2-2 .896-2 2-2 2 .896 2 2zm12-2c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2zm-7 0c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2z"/></g></svg> <div class="actnbr-popover tip tip-top-left actnbr-more"> <div class="tip-arrow"></div> <div class="tip-inner"> <ul> <li class="actnbr-sitename"> <a href="https://herbsutter.com"> <img loading='lazy' alt='' src='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png' srcset='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=75&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1.5x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=100&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 2x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=150&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 3x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=200&d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 4x' class='avatar avatar-50' height='50' width='50' /> Sutter’s Mill </a> </li> <li class="actnbr-folded-follow"> <a class="actnbr-action actnbr-actn-follow " href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path clip-rule="evenodd" d="m4 4.5h12v6.5h1.5v-6.5-1.5h-1.5-12-1.5v1.5 10.5c0 1.1046.89543 2 2 2h7v-1.5h-7c-.27614 0-.5-.2239-.5-.5zm10.5 2h-9v1.5h9zm-5 3h-4v1.5h4zm3.5 1.5h-1v1h1zm-1-1.5h-1.5v1.5 1 1.5h1.5 1 1.5v-1.5-1-1.5h-1.5zm-2.5 2.5h-4v1.5h4zm6.5 1.25h1.5v2.25h2.25v1.5h-2.25v2.25h-1.5v-2.25h-2.25v-1.5h2.25z" fill-rule="evenodd"></path></svg> <span>Subscribe</span> </a> <a class="actnbr-action actnbr-actn-following no-display" href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.5H4V15C4 15.2761 4.22386 15.5 4.5 15.5H11.5V17H4.5C3.39543 17 2.5 16.1046 2.5 15V4.5V3H4H16H17.5V4.5V12.5H16V4.5ZM5.5 6.5H14.5V8H5.5V6.5ZM5.5 9.5H9.5V11H5.5V9.5ZM12 11H13V12H12V11ZM10.5 9.5H12H13H14.5V11V12V13.5H13H12H10.5V12V11V9.5ZM5.5 12H9.5V13.5H5.5V12Z" fill="#008A20"></path><path class="following-icon-tick" d="M13.5 16L15.5 18L19 14.5" stroke="#008A20" stroke-width="1.5"></path></svg> <span>Subscribed</span> </a> </li> <li class="actnbr-signup"><a href="https://wordpress.com/start/">Sign up</a></li> <li class="actnbr-login"><a href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Fherbsutter.com%252F2013%252F12%252F31%252Fgotw-7c-minimizing-compile-time-dependencies-part-3%252F">Log in</a></li> <li class="flb-report"> <a href="https://wordpress.com/abuse/?report_url=https://herbsutter.com" target="_blank" rel="noopener noreferrer"> Report this content </a> </li> <li class="actnbr-reader"> <a href="https://wordpress.com/reader/feeds/171936"> View site in Reader </a> </li> <li class="actnbr-subs"> <a href="https://subscribe.wordpress.com/">Manage subscriptions</a> </li> <li class="actnbr-fold"><a href="">Collapse this bar</a></li> </ul> </div> </div> </li> </ul> </div> <script> window.addEventListener( "load", function( event ) { var link = document.createElement( "link" ); link.href = "https://s0.wp.com/wp-content/mu-plugins/actionbar/actionbar.css?v=20250116"; link.type = "text/css"; link.rel = "stylesheet"; document.head.appendChild( link ); var script = document.createElement( "script" ); script.src = "https://s0.wp.com/wp-content/mu-plugins/actionbar/actionbar.js?v=20250204"; script.defer = true; document.body.appendChild( script ); } ); </script> <script type="text/javascript" src="https://s1.wp.com/wp-content/js/mobile-useragent-info.js?m=1609849039i&ver=20241018" id="mobile-useragent-info-js" defer="defer" data-wp-strategy="defer"></script> <script type="text/javascript" id="custom-content-types-data-js-before"> /* <![CDATA[ */ var CUSTOM_CONTENT_TYPE__INITIAL_STATE; typeof CUSTOM_CONTENT_TYPE__INITIAL_STATE === "object" || (CUSTOM_CONTENT_TYPE__INITIAL_STATE = JSON.parse(decodeURIComponent("%7B%22active%22%3Atrue%2C%22over_ride%22%3Afalse%2C%22should_show_testimonials%22%3Atrue%2C%22should_show_portfolios%22%3Atrue%7D"))); /* ]]> */ </script> <script crossorigin='anonymous' type='text/javascript' src='https://s0.wp.com/_static/??-eJydjEEOgkAMAD9kLWuixoPxLViLdGG7DS3g890v6GWSOczgbkBVgzUwRi7saOsTRV9s3KABzWfxkRc4YXbUfpN3H1L1mP2AP/c+icEsOsFQaXUY5PPHSJTQaREL2I1qaYtHuadL6q6pu6Vz/gLHtU/F'></script> <script type="text/javascript"> (function () { var wpcom_reblog = { source: 'toolbar', toggle_reblog_box_flair: function (obj_id, post_id) { // Go to site selector. This will redirect to their blog if they only have one. const postEndpoint = `https://wordpress.com/post`; // Ideally we would use the permalink here, but fortunately this will be replaced with the // post permalink in the editor. const originalURL = `${ document.location.href }?page_id=${ post_id }`; const url = postEndpoint + '?url=' + encodeURIComponent( originalURL ) + '&is_post_share=true' + '&v=5'; const redirect = function () { if ( ! window.open( url, '_blank' ) ) { location.href = url; } }; if ( /Firefox/.test( navigator.userAgent ) ) { setTimeout( redirect, 0 ); } else { redirect(); } }, }; window.wpcom_reblog = wpcom_reblog; })(); </script> <script src="//stats.wp.com/w.js?68" defer></script> <script type="text/javascript"> _tkq = window._tkq || []; _stq = window._stq || []; _tkq.push(['storeContext', {'blog_id':'3379246','blog_tz':'-8','user_lang':'en','blog_lang':'en','user_id':'0'}]); _stq.push(['view', {'blog':'3379246','v':'wpcom','tz':'-8','user_id':'0','subd':'herbsutter'}]); _stq.push(['extra', {'crypt':'UE40eW5QN0p8M2Y/RE1mNzc2NTVTamdsd0xoLz9RQkM2K298TXY9bERQMXc2MjhEaVZfb2wwakRoSj0mUkp1THptM1NdbkV1WjZIcU9mVWQmPUIvMlN6Jk8wW3NYVEJ3dWZOWExuWD9CbmxqLENKeHZKRG9sOWtMPXxsPzZaPWE9UDdDckNaeEFMRTd6X01ITlUsWnlbaT9+ZDF4Y1MzK3VMNVJEdHppaXVrfjhBRFRfL2pVK11uVzY2VmgtfGFdfCVKbU5wcFF2LnQ/b3E5a21aR3ZUVUolfltJY2Q9bFhMX2V1a0RvRUJsWX5RQ3BSN0NYMXh6cmtYLiZbdG80aFtrW1p6eklIfmtWXSs/OFl2RHc/NUo1N05KY0N8NyZ0aisvaV9MTUJoc1JrWDNjMHxHOUduNiYsbDM='}]); _stq.push([ 'clickTrackerInit', '3379246', '0' ]); </script> <noscript><img src="https://pixel.wp.com/b.gif?v=noscript" style="height:1px;width:1px;overflow:hidden;position:absolute;bottom:1px;" alt="" /></noscript> <script defer id="bilmur" data-customproperties="{"enq_jquery":"1","logged_in":"0","wptheme":"pub\/independent-publisher-2","wptheme_is_block":"0"}" data-provider="wordpress.com" data-service="simple" data-site-tz="Etc/GMT+8" src="/wp-content/js/bilmur-4.min.js?i=12&m=202509"></script><script> ( function() { function getMobileUserAgentInfo() { if ( typeof wpcom_mobile_user_agent_info === 'object' ) { wpcom_mobile_user_agent_info.init(); var mobileStatsQueryString = ''; if ( wpcom_mobile_user_agent_info.matchedPlatformName !== false ) { mobileStatsQueryString += '&x_' + 'mobile_platforms' + '=' + wpcom_mobile_user_agent_info.matchedPlatformName; } if ( wpcom_mobile_user_agent_info.matchedUserAgentName !== false ) { mobileStatsQueryString += '&x_' + 'mobile_devices' + '=' + wpcom_mobile_user_agent_info.matchedUserAgentName; } if ( wpcom_mobile_user_agent_info.isIPad() ) { mobileStatsQueryString += '&x_' + 'ipad_views' + '=' + 'views'; } if ( mobileStatsQueryString != '' ) { new Image().src = document.location.protocol + '//pixel.wp.com/g.gif?v=wpcom-no-pv' + mobileStatsQueryString + '&baba=' + Math.random(); } } } document.addEventListener( 'DOMContentLoaded', getMobileUserAgentInfo ); } )(); </script> </body> </html>