title: Enumerations and pointer-to-members
body: <p>I recently attempted to create an <code>is_class</code> class and needed a way for the compiler to differentiate between enumeration types and class types for which conversion operators are defined. Seeing as how classes, structs and unions are the only types compatible with pointer-to-member functions, I decided to have the compiler determine if the type used to instantiate the <code>is_class</code> template was, in turn, compatible with pointers-to-member functions. After running into several issues, I decided to test the behavior of enumerations when used in conjunction with pointer-to-members and got some wacky results. The following segment illustrates the first quirk:</p>
  
  <pre><code>enum ENUM {};
  void Test(void (ENUM::*pmem) (void))
  {
      /* ... */
  }
  Test(NULL);
  </code></pre>
  
  <p>When compiling with Microsoft Visual C++ 2010, the pointer-to-member portion of the function definition: <code>(ENUM::*pmem)</code> </p>
  
  <p>is highlighted in red and mousing over the declaration reveals the error: </p>
  
  <p><code>Error: "ENUM" is not a class type</code> </p>
  
  <p>However, the compiler parses this segment without encountering any errors, assigning <code>pmem</code> to <code>NULL</code>. It is interesting to me that the compiler would allow this seeing as how enumeration types are not classes, structs or unions and therefore cannot possess methods of their own.</p>
  
  <p>The second point of interest arose when creating a template function, taking a pointer-to-member argument whose type varies:</p>
  
  <pre><code>template&lt;class _Ty&gt;
  void Test_Template(void (_Ty::*pmem) (void))
  {
      /* ... */
  }
  </code></pre>
  
  <p>Of course in order to use this function, it must be explicitly qualified:</p>
  
  <pre><code>Test_Template&lt;ENUM&gt;(NULL);
  </code></pre>
  
  <p>This call however, generates an error stating:</p>
  
  <p><code>invalid explicit template argument(s) for 'void Test(void (__thiscall _Ty::* )(void))'</code></p>
  
  <p>I fixed this issue by creating an additional function template, the prototype of which would match any call that failed to match the prototype for the former template function (which involved using an ellipsis).</p>
  
  <p>Questions:</p>
  
  <ol>
  <li><p>Why is an enumeration compatible with pointers-to-members?</p></li>
  <li><p>Why is there an exact match when invoking the non-template <code>Test</code> function while the compiler generates an error for the template <code>Test_Template</code> explicit qualification?</p></li>
  </ol>