title: Other ways of checking if a class has a certain member function
body: <p>Let's check if</p>
  
  <pre><code>struct Thing {
      int foo(double, bool) {return 0;}
  };
  </code></pre>
  
  <p>has the <code>int foo(double, bool)</code> member function during compile time.  There are many ways of doing this, and most are just variations of others.  Can someone think of a way that is vastly different (or at least fairly creative) than the 5 ways I mention here?  I'm just trying to learn some new techniques with templates and SFINAE.</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  
  // Using void_t (this includes using std::is_detected).
  template &lt;typename T&gt;
  using void_t = void;
  
  template &lt;typename T, typename = void&gt;
  struct has_foo : std::false_type {};
  
  template &lt;typename T&gt;
  struct has_foo&lt;T,
          void_t&lt;decltype(static_cast&lt;int&gt;(std::declval&lt;T&gt;().foo(double{}, bool{})))&gt;
      &gt; : std::true_type {};
  
  // Using the ... default argument.
  template &lt;typename T&gt;
  struct hasfoo {
      template &lt;typename U&gt;
      static std::true_type test (decltype(static_cast&lt;int(T::*)(double, bool)&gt;(&amp;T::foo))*);  // or 'decltype(static_cast&lt;int&gt;(std::declval&lt;U&gt;().foo(double{}, bool{})))*' works fine too.
  
      template &lt;typename&gt;
      static std::false_type test (...);
  
      static constexpr bool value = decltype(test&lt;T&gt;(nullptr))::value;
  };
  
  // Overloads and trailing return types.
  template &lt;typename&gt;
  struct Helper : std::true_type {};
  
  template &lt;typename T&gt;
  auto helper(int) -&gt; Helper&lt;decltype(static_cast&lt;int&gt;(std::declval&lt;T&gt;().foo(double{}, bool{})))&gt;;
  
  template &lt;typename&gt;
  std::false_type helper(long);
  
  template &lt;typename T&gt;
  constexpr bool hasFoo() {return decltype(helper&lt;T&gt;(0))::value;}
  
  // Comma operator (basically the same as the above).
  template &lt;typename T&gt;
  auto check(int) -&gt; decltype(static_cast&lt;int&gt;(std::declval&lt;T&gt;().foo(double{}, bool{})), std::true_type{});
  
  template &lt;typename T&gt;
  std::false_type check(...);
  
  template &lt;typename T&gt;
  using HasFoo = decltype(check&lt;T&gt;(0));
  
  // Member function pointer template parameter.
  template &lt;typename T&gt;
  struct Hasfoo {
      template &lt;typename U, int(U::*)(double, bool)&gt;
      struct Tag;
  
      template &lt;typename U&gt;
      static constexpr bool test (Tag&lt;U, &amp;U::foo&gt;*) {return true;}
  
      template &lt;typename&gt;
      static constexpr bool test (...) {return false;}
  
      static constexpr bool value = test&lt;T&gt;(nullptr);
  };
  
  // Tests
  struct Thing {
      int foo(double, bool) {return 0;}
  };
  
  int main() {
      static_assert (has_foo&lt;Thing&gt;::value, "");
      static_assert (hasfoo&lt;Thing&gt;::value, "");
      static_assert (hasFoo&lt;Thing&gt;(), "");
      static_assert (HasFoo&lt;Thing&gt;::value, "");
  }
  </code></pre>
  
  <p>Edit:  I just remembered an elegant and more general solution that Yakk gave to a different question quite a while ago (here is his actual typing, modified only to match the foo function):</p>
  
  <pre><code>namespace meta {
    namespace details {
      template&lt;template&lt;class...&gt;class Z, class=void, class...Ts&gt;
      struct can_apply : std::false_type {};
      template&lt;template&lt;class...&gt;class Z, class...Ts&gt;
      struct can_apply&lt;Z, decltype((void)(std::declval&lt;Z&lt;Ts...&gt;&gt;())), Ts...&gt;:
        std::true_type
      {};
    }
    template&lt;template&lt;class...&gt;class Z, class...Ts&gt;
    using can_apply = details::can_apply&lt;Z,void,Ts...&gt;;
  }
  
  template&lt;class T&gt;
  using member_foo = decltype(static_cast&lt;int(T::*)(double, bool)&gt;(&amp;T::foo));
  
  template&lt;class T&gt;
  using has_member_foo = meta::can_apply&lt;member_foo, T&gt;;
  </code></pre>