title: How to construct a type trait that can tell if one type's private methods can be called in another type's constructor?
body: <p>I am using C++17.  I have code that is like the following:</p>
  
  <pre><code>#include &lt;type_traits&gt;
  
  template &lt;typename T&gt;
  struct Fooer
  {
      Fooer (T &amp; fooable)
      {
          fooable . foo ();
      }
  };
  
  template &lt;typename T&gt;
  Fooer (T &amp; fooable) -&gt; Fooer &lt;T&gt;;
  
  struct Fooable
  {
  private:
  
      void
      foo ();
  
      friend struct Fooer &lt;Fooable&gt;;
  };
  
  struct NotFooable
  {
  };
  </code></pre>
  
  <p>I want to implement a type trait that can tell if a type is 'Fooable'.</p>
  
  <p>I can't check to see if there's a method <code>foo ()</code> on the type, because it is a private method.  This also doesn't tell me if <code>Fooer</code>'s constructor can call the method.</p>
  
  <pre><code>// Checking for the foo method doesn't work.
  
  template &lt;typename T, typename = void&gt;
  struct HasFoo;
  
  template &lt;typename T, typename&gt;
  struct HasFoo : std::false_type
  {
  };
  
  template &lt;typename T&gt;
  struct HasFoo
  &lt;
      T,
      std::enable_if_t
      &lt;
          std::is_convertible_v &lt;decltype (std::declval &lt;T&gt; () . foo ()), void&gt;
      &gt;
  &gt;
  :   std::true_type
  {
  };
  
  // Both of these assertions fail.
  static_assert (HasFoo &lt;Fooable&gt;::value);
  static_assert (HasFoo &lt;NotFooable&gt;::value);
  </code></pre>
  
  <p>I also can't check to see if <code>Fooer &lt;T&gt;</code> is constructible via <code>std::is_constructible</code>, because <code>std::is_constructible</code> doesn't check to see if the constructor <em>definition</em> is well-formed, only the expression <code>Fooer &lt;T&gt; fooer (std::declval &lt;T&gt; ())</code>.</p>
  
  <pre><code>// Checking constructibility doesn't work either.
  
  template &lt;typename T, typename = void&gt;
  struct CanMakeFooer;
  
  template &lt;typename T, typename&gt;
  struct CanMakeFooer : std::false_type
  {
  };
  
  template &lt;typename T&gt;
  struct CanMakeFooer
  &lt;
      T,
      std::enable_if_t &lt;std::is_constructible_v &lt;Fooer &lt;T&gt;, T &amp;&gt;&gt;
  &gt;
  :   std::true_type
  {
  };
  
  // Neither of these assertions fail.
  static_assert (CanMakeFooer &lt;Fooable&gt;::value);
  static_assert (CanMakeFooer &lt;NotFooable&gt;::value);
  </code></pre>
  
  <p>If I actually try to call the constructors, I get the error that I expect, though it does not get me closer to implementing a type trait.</p>
  
  <pre><code>void
  createFooer ()
  {
      Fooable fooable;
      NotFooable not_fooable;
  
      // This works fine.
      { Fooer fooer (fooable); }
  
      // This correctly generates the compiler error: no member named 'foo' in
      // 'NotFooable'
      { Fooer fooer (not_fooable); } 
  }
  </code></pre>
  
  <p>I want to avoid declaring the type trait as a friend of the Fooable types, and I want to avoid making 'foo' public.</p>
  
  <p>If I could somehow make a type trait check the <em>definition</em> of a function or constructor for well-formedness, I could implement this type trait easily enough, but I don't know how to do that, and I can't find any examples of such a thing on the internet.</p>
  
  <p>Is it possible to do what I want?  How do I do this?</p>