﻿<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <!-- TITLE -->
    <title>SFINAE-friendly std::bind</title>
    <style name="main.css">
        @import url(https://fonts.googleapis.com/css?family=Muli:400,300);
        @import url(https://fonts.googleapis.com/css?family=Share:400,700);
        /* ============================== */
        /* BODY */
        /* ============================== */
        body {
            font-family: 'Muli',arial,sans-serif;
            background-color: #FEFEFE;
            margin: 0;
            padding: 0;
            font-size: 0.875em;
            color: #616161;
        }

        h1, h2, h3, h4, h5, h6 {
            margin-bottom: 0.5em;
            font-family: 'Share';
        }

        .title {
            border-bottom: solid 2px #f5aa10;
        }

        #container {
            margin: 0 auto;
            width: 60%;
            min-width: 640px;
            overflow: auto;
        }

        #main {
            width: 100%;
        }

        a {
            color: #3C6EB4;
            cursor: pointer;
            text-decoration: none;
        }

            a:hover {
                text-decoration: underline;
            }
        /* ============================== */
        /* HEADER */
        /* ============================== */
        #head {
            overflow: auto;
            margin: 40px 0;
        }

            #head div.top {
                font-size: 2.4em;
                margin-right: 80px;
            }

            #head div.bottom {
                height: 38px;
                margin-right: 80px;
            }

            #head .logo {
                vertical-align: bottom;
            }

            #head a.name {
                text-decoration: none;
                color: #555;
                font-weight: bold;
                overflow: auto;
            }

            #head span.slogan {
                color: #CCC;
            }
        /* ============================== */
        /* POST VIEW*/
        /* ============================== */
        article.post {
            margin-bottom: 60px;
            clear: both;
            overflow: auto;
        }

            article.post header.post {
                margin-bottom: 10px;
            }

                article.post header.post h1.title {
                    font-weight: bold;
                    margin: 0;
                }

                    article.post header.post h1.title a {
                        color: inherit;
                        text-decoration: none;
                    }

                article.post header.post div.date {
                    font-size: 0.9em;
                    font-weight: bold;
                    text-align: right;
                    text-transform: uppercase;
                    color: #999;
                }

            article.post .body {
                font-size: 1.2em;
            }

            article.post .console {
                background: url("img/console.png") no-repeat scroll 10px center #F1F1F1;
                display: block;
                line-height: 50px;
                margin: 5px 0;
                padding-left: 60px;
            }

            article.post img:not(.captcha) {
                max-width: 100%;
            }

            article.post blockquote {
                font-size: 1em;
                width: 80%;
                margin-left: 2em;
                padding-left: 0.5em;
                border-left: 2px solid #C3C3C3;
            }

            article.post footer.post {
                clear: both;
                margin-top: 20px;
                text-align: center;
            }

        article pre {
            border: 1px dashed #ccc;
            padding: 1em;
            background: #f4f4f4;
        }

        article.pre, article.code {
            font-family: monospace;
            font-size: 1em;
        }
        /* ============================== */
        /* TABLES */
        /* ============================== */
        table {
            border: 1px solid #999;
        }

            table th, table td {
                background: #f4f4f4;
                padding: 5px 15px;
            }

            table thead {
                border-bottom: 1px solid #999;
            }

            table th {
                font-weight: bold;
                background: #eaeaea;
            }

            table td, table th {
                border-right: 1px solid #999;
            }
    </style>
    <!-- SyntaxHighlighter -->
    <style name="normalize.css">
        article, aside, details, figcaption, figure, footer, header, hgroup, nav, section, summary {
            display: block;
        }

        audio, canvas, video {
            display: inline-block;
        }

            audio:not([controls]) {
                display: none;
                height: 0;
            }

        [hidden] {
            display: none;
        }

        html {
            font-family: sans-serif;
            -webkit-text-size-adjust: 100%;
            -ms-text-size-adjust: 100%;
        }

        a:focus {
            outline: thin dotted;
        }

        a:active, a:hover {
            outline: 0;
        }

        h1 {
            font-size: 2em;
        }

        abbr[title] {
            border-bottom: 1px dotted;
        }

        b, strong {
            font-weight: 700;
        }

        dfn {
            font-style: italic;
        }

        mark {
            background: #ff0;
            color: #000;
        }

        code, kbd, pre, samp {
            font-family: monospace, serif;
            font-size: 1em;
        }

        pre {
            white-space: pre-wrap;
            word-wrap: break-word;
        }

        q {
            quotes: \201C \201D \2018 \2019;
        }

        small {
            font-size: 80%;
        }

        sub, sup {
            font-size: 75%;
            line-height: 0;
            position: relative;
            vertical-align: baseline;
        }

        sup {
            top: -.5em;
        }

        sub {
            bottom: -.25em;
        }

        img {
            border: 0;
        }

        svg:not(:root) {
            overflow: hidden;
        }

        fieldset {
            border: 1px solid silver;
            margin: 0 2px;
            padding: .35em .625em .75em;
        }

        button, input, select, textarea {
            font-family: inherit;
            font-size: 100%;
            margin: 0;
        }

        button, input {
            line-height: normal;
        }

            button, html input[type=button], /* 1 */
            input[type=reset], input[type=submit] {
                -webkit-appearance: button;
                cursor: pointer;
            }

                button[disabled], input[disabled] {
                    cursor: default;
                }

            input[type=checkbox], input[type=radio] {
                box-sizing: border-box;
                padding: 0;
            }

            input[type=search] {
                -webkit-appearance: textfield;
                -moz-box-sizing: content-box;
                -webkit-box-sizing: content-box;
                box-sizing: content-box;
            }

                input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration {
                    -webkit-appearance: none;
                }

        textarea {
            overflow: auto;
            vertical-align: top;
        }

        table {
            border-collapse: collapse;
            border-spacing: 0;
        }

        body, figure {
            margin: 0;
        }

        legend, button::-moz-focus-inner, input::-moz-focus-inner {
            border: 0;
            padding: 0;
        }
    </style>
    <style name="shCore.css">
        .syntaxhighlighter a,
        .syntaxhighlighter div,
        .syntaxhighlighter code,
        .syntaxhighlighter table,
        .syntaxhighlighter table td,
        .syntaxhighlighter table tr,
        .syntaxhighlighter table tbody,
        .syntaxhighlighter table thead,
        .syntaxhighlighter table caption,
        .syntaxhighlighter textarea {
            -moz-border-radius: 0 0 0 0 !important;
            -webkit-border-radius: 0 0 0 0 !important;
            background: none !important;
            border: 0 !important;
            bottom: auto !important;
            float: none !important;
            height: auto !important;
            left: auto !important;
            line-height: 1.1em !important;
            margin: 0 !important;
            outline: 0 !important;
            overflow: visible !important;
            padding: 0 !important;
            position: static !important;
            right: auto !important;
            text-align: left !important;
            top: auto !important;
            vertical-align: baseline !important;
            width: auto !important;
            box-sizing: content-box !important;
            font-family: monospace !important;
            font-weight: normal !important;
            font-style: normal !important;
            font-size: 1em !important;
            min-height: inherit !important;
            min-height: auto !important;
        }

        .syntaxhighlighter {
            margin: 1em 0 1em 0 !important;
            overflow: auto !important;
            font-size: 1em !important;
        }

            .syntaxhighlighter.source {
                overflow: hidden !important;
            }

            .syntaxhighlighter .bold {
                font-weight: bold !important;
            }

            .syntaxhighlighter .italic {
                font-style: italic !important;
            }

            .syntaxhighlighter .line {
                white-space: pre !important;
            }

            .syntaxhighlighter table {
                width: 100% !important;
            }

                .syntaxhighlighter table caption {
                    text-align: left !important;
                    padding: .5em 0 0.5em 1em !important;
                }

                .syntaxhighlighter table td.code {
                    width: 100% !important;
                }

                    .syntaxhighlighter table td.code .container {
                        position: relative !important;
                    }

                        .syntaxhighlighter table td.code .container textarea {
                            box-sizing: border-box !important;
                            position: absolute !important;
                            left: 0 !important;
                            top: 0 !important;
                            width: 100% !important;
                            height: 100% !important;
                            border: none !important;
                            background: white !important;
                            padding-left: 1em !important;
                            overflow: hidden !important;
                            white-space: pre !important;
                        }

                .syntaxhighlighter table td.gutter .line {
                    text-align: right !important;
                    padding: 0 0.5em 0 1em !important;
                }

                .syntaxhighlighter table td.code .line {
                    padding: 0 1em !important;
                }

            .syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
                padding-left: 0em !important;
            }

            .syntaxhighlighter.show {
                display: block !important;
            }

            .syntaxhighlighter.collapsed table {
                display: none !important;
            }

            .syntaxhighlighter.collapsed .toolbar {
                padding: 0.1em 0.8em 0em 0.8em !important;
                font-size: 1em !important;
                position: static !important;
                width: auto !important;
                height: auto !important;
            }

                .syntaxhighlighter.collapsed .toolbar span {
                    display: inline !important;
                    margin-right: 1em !important;
                }

                    .syntaxhighlighter.collapsed .toolbar span a {
                        padding: 0 !important;
                        display: none !important;
                    }

                        .syntaxhighlighter.collapsed .toolbar span a.expandSource {
                            display: inline !important;
                        }

            .syntaxhighlighter .toolbar {
                position: absolute !important;
                right: 1px !important;
                top: 1px !important;
                width: 11px !important;
                height: 11px !important;
                font-size: 10px !important;
                z-index: 10 !important;
            }

                .syntaxhighlighter .toolbar span.title {
                    display: inline !important;
                }

                .syntaxhighlighter .toolbar a {
                    display: block !important;
                    text-align: center !important;
                    text-decoration: none !important;
                    padding-top: 1px !important;
                }

                    .syntaxhighlighter .toolbar a.expandSource {
                        display: none !important;
                    }

            .syntaxhighlighter.ie {
                font-size: .9em !important;
                padding: 1px 0 1px 0 !important;
            }

                .syntaxhighlighter.ie .toolbar {
                    line-height: 8px !important;
                }

                    .syntaxhighlighter.ie .toolbar a {
                        padding-top: 0px !important;
                    }

            .syntaxhighlighter.printing .line.alt1 .content,
            .syntaxhighlighter.printing .line.alt2 .content,
            .syntaxhighlighter.printing .line.highlighted .number,
            .syntaxhighlighter.printing .line.highlighted.alt1 .content,
            .syntaxhighlighter.printing .line.highlighted.alt2 .content {
                background: none !important;
            }

            .syntaxhighlighter.printing .line .number {
                color: #bbbbbb !important;
            }

            .syntaxhighlighter.printing .line .content {
                color: black !important;
            }

            .syntaxhighlighter.printing .toolbar {
                display: none !important;
            }

            .syntaxhighlighter.printing a {
                text-decoration: none !important;
            }

            .syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
                color: black !important;
            }

            .syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
                color: #008200 !important;
            }

            .syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
                color: blue !important;
            }

            .syntaxhighlighter.printing .keyword {
                color: #006699 !important;
                font-weight: bold !important;
            }

            .syntaxhighlighter.printing .preprocessor {
                color: gray !important;
            }

            .syntaxhighlighter.printing .variable {
                color: #aa7700 !important;
            }

            .syntaxhighlighter.printing .value {
                color: #009900 !important;
            }

            .syntaxhighlighter.printing .functions {
                color: #ff1493 !important;
            }

            .syntaxhighlighter.printing .constants {
                color: #0066cc !important;
            }

            .syntaxhighlighter.printing .script {
                font-weight: bold !important;
            }

            .syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
                color: gray !important;
            }

            .syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
                color: #ff1493 !important;
            }

            .syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
                color: red !important;
            }

            .syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
                color: black !important;
            }
    </style>
    <style name="shThemeDefault.css">
        .syntaxhighlighter {
            background-color: #f4f4f4 !important;
            border: 1px dashed #ccc;
            padding: 1em;
        }

            .syntaxhighlighter .line.alt1 {
                background-color: #f4f4f4 !important;
            }

            .syntaxhighlighter .line.alt2 {
                background-color: #f4f4f4 !important;
            }

            .syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
                background-color: #e0e0e0 !important;
            }

            .syntaxhighlighter .line.highlighted.number {
                color: black !important;
            }

            .syntaxhighlighter table caption {
                color: black !important;
            }

            .syntaxhighlighter .gutter {
                color: #afafaf !important;
            }

                .syntaxhighlighter .gutter .line {
                    border-right: 3px solid #6ce26c !important;
                }

                    .syntaxhighlighter .gutter .line.highlighted {
                        background-color: #6ce26c !important;
                        color: white !important;
                    }

            .syntaxhighlighter.printing .line .content {
                border: none !important;
            }

            .syntaxhighlighter.collapsed {
                overflow: visible !important;
            }

                .syntaxhighlighter.collapsed .toolbar {
                    color: blue !important;
                    background: #f4f4f4 !important;
                    border: 1px solid #6ce26c !important;
                }

                    .syntaxhighlighter.collapsed .toolbar a {
                        color: blue !important;
                    }

                        .syntaxhighlighter.collapsed .toolbar a:hover {
                            color: red !important;
                        }

            .syntaxhighlighter .toolbar {
                color: #f4f4f4 !important;
                background: #6ce26c !important;
                border: none !important;
            }

                .syntaxhighlighter .toolbar a {
                    color: #f4f4f4 !important;
                }

                    .syntaxhighlighter .toolbar a:hover {
                        color: black !important;
                    }

            .syntaxhighlighter .plain, .syntaxhighlighter .plain a {
                color: black !important;
            }

            .syntaxhighlighter .comments, .syntaxhighlighter .comments a {
                color: #008200 !important;
            }

            .syntaxhighlighter .string, .syntaxhighlighter .string a {
                color: blue !important;
            }

            .syntaxhighlighter .keyword {
                color: #006699 !important;
            }

            .syntaxhighlighter .preprocessor {
                color: gray !important;
            }

            .syntaxhighlighter .variable {
                color: #aa7700 !important;
            }

            .syntaxhighlighter .value {
                color: #009900 !important;
            }

            .syntaxhighlighter .functions {
                color: #ff1493 !important;
            }

            .syntaxhighlighter .constants {
                color: #0066cc !important;
            }

            .syntaxhighlighter .script {
                font-weight: bold !important;
                color: #006699 !important;
                background-color: none !important;
            }

            .syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
                color: gray !important;
            }

            .syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
                color: #ff1493 !important;
            }

            .syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
                color: red !important;
            }

            .syntaxhighlighter .keyword {
                font-weight: bold !important;
            }
    </style>
</head>
<body>

    <div id="container">
        <section id="main">
            <article class="post">
                <p>
                    Document number: P0826R0<br>
                    Date: 2017-10-12<br>
                    Project: Programming Language C++, Library Evolution Working Group<br>
                    Reply-to: Agustín Bergé <a href="mailto:agustinberge@gmail.com">agustinberge@gmail.com</a>
                </p>

                <a name="sfinae-friendly-`stdbind`" href="#sfinae-friendly-`stdbind`"><h1>SFINAE-friendly <code>std::bind</code></h1></a>

                <a name="tension-between-sfinae-and-deduced-return-types" href="#tension-between-sfinae-and-deduced-return-types"><h2>Tension Between SFINAE and Deduced Return Types</h2></a>

                <a name="1.-introduction" href="#1.-introduction"><h2>1. Introduction</h2></a>

                <p>This paper proposes mandating that the call wrapper returned from <code>std::bind</code> be SFINAE-friendly, and explores the implications a SFINAE-friendly call wrapper has for deduced return types on the target callable.</p>

                <a name="2.-discussion" href="#2.-discussion"><h2>2. Discussion</h2></a>

                <p>In a nutshell, bind expressions are not SFINAE-friendly. As a consequence, they do not play nice with <code>std::is_invocable</code>; simply asking the question may result in the program being ill-formed. Implementations diverge in their level of SFINAE-friendliness, resulting in a poor user experience when <code>std::bind</code> is mixed with facilities built on top of SFINAE like <code>std::is_invocable</code>, <code>std::result_of</code>, <code>std::function</code>, and more recently concepts and constraints.</p>

                <p>A SFINAE-friendly bind expression implementation requires checking that there are sufficient unbound arguments to fulfill all placeholders, and either constraining all function call operators on the well-formedness of their corresponding call expressions, or performing any return type computation in an immediate context, such that substitution failures do not render the program ill-formed.</p>

                <a name="2.1-on-poisonous-overloads" href="#2.1-on-poisonous-overloads"><h3>2.1 On Poisonous Overloads</h3></a>

                <p>When target callables that are not SFINAE-friendly are used together with a SFINAE-friendly call wrapper the result is, unsurprisingly, a SFINAE-unfriendly callable. There is a more subtle interaction, however, in that different cv/ref-qualified function call operator overloads involve slightly different call expressions each, and any one of them could render the program ill-formed, regardless of the well-formedness of the others. In a worst case scenario, these poisonous overloads may cause the wrapping of a SFINAE-unfriendly callable within a SFINAE-friendly call wrapper to result in a callable which is ill-formed for every call expression:</p>

                <div>
                    <div id="highlighter_900520" class="syntaxhighlighter nogutter  cpp">
                        <table border="0" cellspacing="0" cellpadding="0">
                            <tbody>
                                <tr>
                                    <td class="code">
                                        <div class="container">
                                            <div class="line number1 index0 alt2"><code class="cpp comments">// SFINAE-unfriendly callable</code></div>
                                            <div class="line number2 index1 alt1"><code class="cpp keyword bold">struct</code> <code class="cpp plain">sfinae_unfriendly {</code></div>
                                            <div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">First, </code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Rest&gt;</code></div>
                                            <div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">struct</code> <code class="cpp plain">returns {</code></div>
                                            <div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">static_assert</code><code class="cpp plain">(</code></div>
                                            <div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">!</code><code class="cpp color1 bold">std::is_floating_point_v</code><code class="cpp plain">&lt;First&gt;,</code></div>
                                            <div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp string">"First argument can't be a floating point type"</code><code class="cpp plain">);</code></div>
                                            <div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">using</code> <code class="cpp plain">type = First;</code></div>
                                            <div class="line number9 index8 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">};</code></div>
                                            <div class="line number10 index9 alt1">&nbsp;</div>
                                            <div class="line number11 index10 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Args&gt;</code></div>
                                            <div class="line number12 index11 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">auto</code> <code class="cpp keyword bold">operator</code><code class="cpp plain">()(Args&amp;&amp;... args) </code><code class="cpp keyword bold">const</code></div>
                                            <div class="line number13 index12 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">-&gt; </code><code class="cpp keyword bold">typename</code> <code class="cpp plain">returns&lt;Args...&gt;::type</code></div>
                                            <div class="line number14 index13 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">{ </code><code class="cpp comments">/*...*/</code> <code class="cpp plain">}</code></div>
                                            <div class="line number15 index14 alt2"><code class="cpp plain">};</code></div>
                                            <div class="line number16 index15 alt1">&nbsp;</div>
                                            <div class="line number17 index16 alt2"><code class="cpp comments">// SFINAE-friendly call wrapper</code></div>
                                            <div class="line number18 index17 alt1"><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">F&gt;</code></div>
                                            <div class="line number19 index18 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">call_wrapper {</code></div>
                                            <div class="line number20 index19 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">F _f;</code></div>
                                            <div class="line number21 index20 alt2">&nbsp;</div>
                                            <div class="line number22 index21 alt1"><code class="cpp keyword bold">public</code><code class="cpp plain">:</code></div>
                                            <div class="line number23 index22 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">call_wrapper(F f) : _f(</code><code class="cpp color1 bold">std::move</code><code class="cpp plain">(f)) {}</code></div>
                                            <div class="line number24 index23 alt1">&nbsp;</div>
                                            <div class="line number25 index24 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Args&gt;</code></div>
                                            <div class="line number26 index25 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">auto</code> <code class="cpp keyword bold">operator</code><code class="cpp plain">()(Args&amp;&amp;... args) </code><code class="cpp keyword bold">const</code> <code class="cpp comments">// const prepends an int</code></div>
                                            <div class="line number27 index26 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">-&gt; </code><code class="cpp color1 bold">std::invoke_result_t</code><code class="cpp plain">&lt;F </code><code class="cpp keyword bold">const</code><code class="cpp plain">&amp;, </code><code class="cpp color1 bold">int</code><code class="cpp plain">, Args...&gt;</code></div>
                                            <div class="line number28 index27 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">{ </code><code class="cpp keyword bold">return</code> <code class="cpp plain">_f(1, </code><code class="cpp color1 bold">std::forward</code><code class="cpp plain">&lt;Args&gt;(args)...); }</code></div>
                                            <div class="line number29 index28 alt2">&nbsp;</div>
                                            <div class="line number30 index29 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Args&gt;</code></div>
                                            <div class="line number31 index30 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">auto</code> <code class="cpp keyword bold">operator</code><code class="cpp plain">()(Args&amp;&amp;... args) </code><code class="cpp keyword bold">volatile</code> <code class="cpp comments">// volatile prepends a double</code></div>
                                            <div class="line number32 index31 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">-&gt; </code><code class="cpp color1 bold">std::invoke_result_t</code><code class="cpp plain">&lt;F </code><code class="cpp keyword bold">volatile</code><code class="cpp plain">&amp;, </code><code class="cpp color1 bold">double</code><code class="cpp plain">, Args...&gt;</code></div>
                                            <div class="line number33 index32 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">{ </code><code class="cpp keyword bold">return</code> <code class="cpp plain">_f(1.0, </code><code class="cpp color1 bold">std::forward</code><code class="cpp plain">&lt;Args&gt;(args)...); }</code></div>
                                            <div class="line number34 index33 alt1"><code class="cpp plain">};</code></div>
                                            <div class="line number35 index34 alt2">&nbsp;</div>
                                            <div class="line number36 index35 alt1"><code class="cpp comments">// attempt to call const-qualified operator(),</code></div>
                                            <div class="line number37 index36 alt2"><code class="cpp comments">// which calls sfinae_unfriendly with int argument</code></div>
                                            <div class="line number38 index37 alt1"><code class="cpp plain">call_wrapper </code><code class="cpp keyword bold">const</code> <code class="cpp plain">w = sfinae_unfriendly{};</code></div>
                                            <div class="line number39 index38 alt2"><code class="cpp plain">w(); </code><code class="cpp comments">// error: static assertion failed</code></div>
                                            <div class="line number40 index39 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//&nbsp;&nbsp; static_assert(!std::is_floating_point_v&lt;First&gt;)</code></div>
                                            <div class="line number41 index40 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">// required by substitution of</code></div>
                                            <div class="line number42 index41 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//&nbsp;&nbsp; std::invoke_result_t&lt;sfinae_unfriendly </code><code class="cpp comments bold">volatile</code><code class="cpp comments">&amp;, double, Args...&gt;</code></div>
                                            <div class="line number43 index42 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//&nbsp;&nbsp; call_wrapper&lt;sfinae_unfriendly&gt;::operator()&lt;Args...&gt;(Args&amp;&amp;...) </code><code class="cpp comments bold">volatile</code></div>
                                            <div class="line number44 index43 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//&nbsp;&nbsp; [with Args = {}]'</code></div>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <p>This is not a new problem, but it is becoming a more common one. Deduced return types are notably SFINAE-unfriendly:</p>

                <blockquote>
                    <p>
                        <strong>10.1.7.4 [dcl.spec.auto]/10</strong>
                        Return type deduction for a function template with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a <code>return</code> statement with a non-type-dependent operand. <em>[Note:</em> Therefore, any use of a specialization of the function template will cause an implicit instantiation. Any errors that arise from this instantiation are not in the immediate context of the function type and can result in the program being ill-formed. <em>—end note]</em> <em>[...]</em>
                    </p>
                </blockquote>

                <p>As modern C++ practices push for deduced return types, SFINAE-based facilities suffer. There's tension between them, and something's gotta give...</p>

                <a name="2.2-on-poisoned-bind-expressions" href="#2.2-on-poisoned-bind-expressions"><h3>2.2 On Poisoned bind expressions</h3></a>

                <p>The following similar scenario has been reported as a bug against <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80564" title="Bug 80564 - bind on SFINAE unfriendly generic lambda - libstdc++">libstdc++</a> and <a href="https://bugs.llvm.org/show_bug.cgi?id=32856" title="Bug 32856 - bind on generic lambda - libc++">libc++</a>:</p>

                <div>
                    <div id="highlighter_688316" class="syntaxhighlighter nogutter  cpp">
                        <table border="0" cellspacing="0" cellpadding="0">
                            <tbody>
                                <tr>
                                    <td class="code">
                                        <div class="container">
                                            <div class="line number1 index0 alt2"><code class="cpp color1 bold">int</code> <code class="cpp plain">i;</code></div>
                                            <div class="line number2 index1 alt1"><code class="cpp color1 bold">std::bind</code><code class="cpp plain">([](</code><code class="cpp keyword bold">auto</code><code class="cpp plain">&amp; x) -&gt; </code><code class="cpp keyword bold">void</code> <code class="cpp plain">{ x = 1; }, i)(); </code><code class="cpp comments">// fine</code></div>
                                            <div class="line number3 index2 alt2"><code class="cpp color1 bold">std::bind</code><code class="cpp plain">([](</code><code class="cpp keyword bold">auto</code><code class="cpp plain">&amp; x) { x = 1; }, i)(); </code><code class="cpp comments">// error: assignment of read-only reference 'x'</code></div>
                                            <div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">// required by substitution of</code></div>
                                            <div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//&nbsp;&nbsp; Result std::_Bind&lt;lambda(auto&amp;), int&gt;::operator()&lt;Args..., Result&gt;(Args&amp;&amp;...) </code><code class="cpp comments bold">const</code></div>
                                            <div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//&nbsp;&nbsp; [with Args = {}; Result = &lt;missing&gt;]</code></div>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <p><em>[Note:</em> It may seem that this snippet attempts to modify <code>i</code>, but it actually attempts to modify a bound argument initialized from it; this is only viable for a non-const bind expression. The const-qualified operator overload poisons the call in the deduced return type case. <em>—end note]</em></p>

                <p>The reports further claim that the above failure is due to non-conforming implementations, caused by their SFINAE-friendliness —be it deliberate or accidental—. Instead, it has been suggested that bind expressions in particular and forwarding call wrappers in general should be mandated to <strong>NOT</strong> be SFINAE-friendly, so that they may themselves be implemented using deduced return types:</p>

                <div>
                    <div id="highlighter_546566" class="syntaxhighlighter nogutter  cpp">
                        <table border="0" cellspacing="0" cellpadding="0">
                            <tbody>
                                <tr>
                                    <td class="code">
                                        <div class="container">
                                            <div class="line number1 index0 alt2"><code class="cpp comments">// SFINAE-unfriendly call wrapper</code></div>
                                            <div class="line number2 index1 alt1"><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">F&gt;</code></div>
                                            <div class="line number3 index2 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">call_wrapper {</code></div>
                                            <div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp comments">/*...*/</code></div>
                                            <div class="line number5 index4 alt2">&nbsp;</div>
                                            <div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Args&gt;</code></div>
                                            <div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">decltype</code><code class="cpp plain">(</code><code class="cpp keyword bold">auto</code><code class="cpp plain">) </code><code class="cpp keyword bold">operator</code><code class="cpp plain">()(Args&amp;&amp;... args) </code><code class="cpp keyword bold">const</code> <code class="cpp comments">// const prepends an int</code></div>
                                            <div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">{ </code><code class="cpp keyword bold">return</code> <code class="cpp plain">_f(1, </code><code class="cpp color1 bold">std::forward</code><code class="cpp plain">&lt;Args&gt;(args)...); }</code></div>
                                            <div class="line number9 index8 alt2">&nbsp;</div>
                                            <div class="line number10 index9 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Args&gt;</code></div>
                                            <div class="line number11 index10 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">decltype</code><code class="cpp plain">(</code><code class="cpp keyword bold">auto</code><code class="cpp plain">) </code><code class="cpp keyword bold">operator</code><code class="cpp plain">()(Args&amp;&amp;... args) </code><code class="cpp keyword bold">volatile</code> <code class="cpp comments">// volatile prepends a double</code></div>
                                            <div class="line number12 index11 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">{ </code><code class="cpp keyword bold">return</code> <code class="cpp plain">_f(1.0, </code><code class="cpp color1 bold">std::forward</code><code class="cpp plain">&lt;Args&gt;(args)...); }</code></div>
                                            <div class="line number13 index12 alt2"><code class="cpp plain">};</code></div>
                                            <div class="line number14 index13 alt1">&nbsp;</div>
                                            <div class="line number15 index14 alt2"><code class="cpp plain">call_wrapper </code><code class="cpp keyword bold">const</code> <code class="cpp plain">w = sfinae_unfriendly{};</code></div>
                                            <div class="line number16 index15 alt1"><code class="cpp plain">w(); </code><code class="cpp comments">// fine, calls const-qualified operator()</code></div>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <p>This paper does not consider such approach an adequate solution to the problem. Instead, it proposes to continue the SFINAE-friendly trend that started with <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3462.html" title="std::result_of and SFINAE - Eric Niebler, et. al.">N3462</a> —<code>std::result_of</code> and SFINAE— and gave rise to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0077r2.html" title="is_callable, the missing INVOKE related trait - Agustín Bergé">P0077</a> —<code>is_callable</code>, the missing INVOKE related trait—; trend that has been reconfirmed in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0358r1.html" title="Fixes for not_fn - Tomasz Kaminski">P0358</a> —Fixes for <code>not_fn</code>—.</p>

                <a name="2.3-on-deleted-overloads" href="#2.3-on-deleted-overloads"><h3>2.3 On Deleted Overloads</h3></a>

                <p>A SFINAE-friendly implementation has to be careful to not fall back to a const-qualified overload when the non-const invoke expression is not well-formed. A naive implementation might fail to correctly propagate the cv-qualifiers of the call wrapper, causing it to accept the following ill-formed snippet:</p>

                <div>
                    <div id="highlighter_492362" class="syntaxhighlighter nogutter  cpp">
                        <table border="0" cellspacing="0" cellpadding="0">
                            <tbody>
                                <tr>
                                    <td class="code">
                                        <div class="container">
                                            <div class="line number1 index0 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">fun {</code></div>
                                            <div class="line number2 index1 alt1"><code class="cpp spaces">&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Args&gt;</code></div>
                                            <div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;</code><code class="cpp keyword bold">void</code> <code class="cpp keyword bold">operator</code><code class="cpp plain">()(Args&amp;&amp;... args) = </code><code class="cpp keyword bold">delete</code><code class="cpp plain">;</code></div>
                                            <div class="line number4 index3 alt1">&nbsp;</div>
                                            <div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;</code><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">...Args&gt;</code></div>
                                            <div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;</code><code class="cpp color1 bold">bool</code> <code class="cpp keyword bold">operator</code><code class="cpp plain">()(Args&amp;&amp;... args) </code><code class="cpp keyword bold">const</code> <code class="cpp plain">{ </code><code class="cpp keyword bold">return</code> <code class="cpp keyword bold">true</code><code class="cpp plain">; }</code></div>
                                            <div class="line number7 index6 alt2"><code class="cpp plain">};</code></div>
                                            <div class="line number8 index7 alt1">&nbsp;</div>
                                            <div class="line number9 index8 alt2"><code class="cpp color1 bold">std::bind</code><code class="cpp plain">(fun{})(); </code><code class="cpp comments">// error: call to deleted function</code></div>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <p>It should be noted that this differs from the required behavior for <code>std::not_fn</code> —as specified in the current working draft <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4687.pdf" title="Working Draft, Standard for Programming Language C++">N4687</a>—, which might be considered a defect:</p>

                <div>
                    <div id="highlighter_822141" class="syntaxhighlighter nogutter  cpp">
                        <table border="0" cellspacing="0" cellpadding="0">
                            <tbody>
                                <tr>
                                    <td class="code">
                                        <div class="container">
                                            <div class="line number1 index0 alt2"><code class="cpp color1 bold">std::not_fn</code><code class="cpp plain">(fun{})(); </code><code class="cpp comments">// fine, returns false</code></div>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <a name="3.-implementation-experience" href="#3.-implementation-experience"><h2>3. Implementation Experience</h2></a>

                <ul>
                    <li><p><strong>libc++</strong>: SFINAE-friendly, as a result of <a href="https://bugs.llvm.org/show_bug.cgi?id=15295" title="Bug 15295 - std::bind result can't be used in SFINAE context - libc++">this</a> issue report.</p></li>
                    <li><p><strong>libstdc++</strong>: SFINAE-friendly for <code>std::bind</code> but not <code>std::bind&lt;R&gt;</code>, unintentional?</p></li>
                    <li><p><strong>MSVC</strong>: Not SFINAE-friendly, triggers diagnostic in <code>std::tuple_element</code> when there are not enough unbound arguments to satisfy all placeholders.</p></li>
                </ul>

                <p>All three implementations yield a compilation error for the following snippet:</p>

                <div>
                    <div id="highlighter_723454" class="syntaxhighlighter nogutter  cpp">
                        <table border="0" cellspacing="0" cellpadding="0">
                            <tbody>
                                <tr>
                                    <td class="code">
                                        <div class="container">
                                            <div class="line number1 index0 alt2"><code class="cpp color1 bold">std::bind</code><code class="cpp plain">([](</code><code class="cpp keyword bold">auto</code><code class="cpp plain">&amp; x) -&gt; </code><code class="cpp keyword bold">void</code> <code class="cpp plain">{ x = 1; }, 42)(); </code><code class="cpp comments">// fine</code></div>
                                            <div class="line number2 index1 alt1"><code class="cpp color1 bold">std::bind</code><code class="cpp plain">([](</code><code class="cpp keyword bold">auto</code><code class="cpp plain">&amp; x) { x = 1; }, 42)(); </code><code class="cpp comments">// error</code></div>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <ul>
                    <li><strong>Boost</strong>: Not SFINAE-friendly, return type computation relies on nested <code>result_type</code>; all call expressions appear well-formed in unevaluated contexts.</li>
                </ul>

                <p>Only libc++, the SFINAE-friendly implementation, yields a compilation error for the following snippet:</p>

                <div>
                    <div id="highlighter_964489" class="syntaxhighlighter nogutter  cpp">
                        <table border="0" cellspacing="0" cellpadding="0">
                            <tbody>
                                <tr>
                                    <td class="code">
                                        <div class="container">
                                            <div class="line number1 index0 alt2"><code class="cpp color1 bold">std::bind</code><code class="cpp plain">([](</code><code class="cpp keyword bold">auto</code><code class="cpp plain">&amp; x) -&gt; </code><code class="cpp keyword bold">void</code> <code class="cpp plain">{ x = 1; }, 42)(); </code><code class="cpp comments">// fine</code></div>
                                            <div class="line number2 index1 alt1"><code class="cpp color1 bold">std::bind</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">void</code><code class="cpp plain">&gt;([](</code><code class="cpp keyword bold">auto</code><code class="cpp plain">&amp; x) { x = 1; }, 42)(); </code><code class="cpp comments">// error</code></div>
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <a name="4.-references" href="#4.-references"><h2>4. References</h2></a>

                <ul>
                    <li>
                        <p>
                            <strong>[N4687]</strong> ISO/IEC JTC1 SC22 WG21, Programming Languages - C++, working draft, July 2017<br>
                            <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4687.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4687.pdf</a>
                        </p>
                    </li>
                    <li>
                        <p>
                            <strong>[N3462]</strong> <code>std::result_of</code> and SFINAE - Eric Niebler, et. al.<br>
                            <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3462.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3462.html</a>
                        </p>
                    </li>
                    <li>
                        <p>
                            <strong>[P0077]</strong> <code>is_callable</code>, the missing INVOKE related trait - Agustín Bergé<br>
                            <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0077r2.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0077r2.html</a>
                        </p>
                    </li>
                    <li>
                        <p>
                            <strong>[P0358]</strong> Fixes for <code>not_fn</code> - Tomasz Kamiński<br>
                            <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0358r1.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0358r1.html</a>
                        </p>
                    </li>
                </ul>
            </article>
        </section>
</body>
</html>