title: Stripping all qualifiers from a function type
body: <p>Given a possibly varargs function type with possibly a <em>cv-qualifier-seq</em> and possibly a <em>ref-qualifier</em>, is it possible to write a type trait that strips all the qualifiers without writing 4 * 3 * 2 = 24 partial specializations?</p>
  
  <pre><code>template&lt;class T&gt;
  struct strip_function_qualifiers;
  
  template&lt;class R, class... Args&gt;
  struct strip_function_qualifiers&lt;R(Args...)&gt; { using type = R(Args...); };
  
  template&lt;class R, class... Args&gt;
  struct strip_function_qualifiers&lt;R(Args..., ...)&gt; { using type = R(Args..., ...); };
  
  template&lt;class R, class... Args&gt;
  struct strip_function_qualifiers&lt;R(Args...) const&gt; { using type = R(Args...); };
  
  template&lt;class R, class... Args&gt;
  struct strip_function_qualifiers&lt;R(Args..., ...) const &gt; { using type = R(Args..., ...); };
  
  template&lt;class R, class... Args&gt;
  struct strip_function_qualifiers&lt;R(Args...) const &amp;&gt; { using type = R(Args...); };
  
  template&lt;class R, class... Args&gt;
  struct strip_function_qualifiers&lt;R(Args..., ...) const &amp; &gt; { using type = R(Args..., ...); };
  
  // etc. etc. for each possible combination (24 in total)
  </code></pre>
  
  <p>And with <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4301.pdf" rel="noreferrer">the new transactional memory TS</a> adding <code>transaction_safe</code> to the mix, does that mean we'll need to write 48 partial specializations for this?</p>
  
  <hr>
  
  <p><strong>Edit</strong>: Quoting the description of these weird function types ([dcl.fct]/p6, quoting N4140):</p>
  
  <blockquote>
    <p>A function type with a <em>cv-qualifier-seq</em> or a <em>ref-qualifier</em>
    (including a type named by typedef-name (7.1.3, 14.1)) shall appear
    only as:</p>
    
    <ul>
    <li>the function type for a non-static member function,</li>
    <li>the function type to which a pointer to member refers,</li>
    <li>the top-level function type of a function typedef declaration or <em>alias-declaration</em>, </li>
    <li>the <em>type-id</em> in the default argument of a type-parameter (14.1), or</li>
    <li>the <em>type-id</em> of a <em>template-argument</em> for a <em>type-parameter</em> (14.3.1).</li>
    </ul>
    
    <p>[ <em>Example</em>:</p>
  
  <pre><code>typedef int FIC(int) const;
  FIC f; // ill-formed: does not declare a member function
  struct S {
     FIC f; // OK
  };
  FIC S::*pm = &amp;S::f; // OK
  </code></pre>
    
    <p>— <em>end example</em> ] </p>
    
    <p>The effect of a <em>cv-qualifier-seq</em> in a function
    declarator is not the same as adding cv-qualification on top of the
    function type. In the latter case, the <em>cv-qualifiers</em> are ignored.
    [<em>Note</em>: a function type that has a <em>cv-qualifier-seq</em> is not a
    cv-qualified type; there are no cv-qualified function types. — <em>end
    note</em> ] [ <em>Example</em>:</p>
  
  <pre><code> typedef void F();
   struct S {
      const F f; // OK: equivalent to: void f();
   };
  </code></pre>
    
    <p>— <em>end example</em> ] </p>
    
    <p><strong>The return type, the <em>parameter-type-list</em>, the
    <em>ref-qualifier</em>, and the <em>cv-qualifier-seq</em>, but not the default arguments (8.3.6) or the exception specification (15.4), are part of
    the function type.</strong> [<em>Note</em>: Function types are checked during the
    assignments and initializations of pointers to functions, references
    to functions, and pointers to member functions. — <em>end note</em> ]</p>
  </blockquote>