Search code examples
c++templatestemplate-specialization

Is f(U(*)()) just a specialized version of f(U*)?


When reading a wiki page, I found this sample code

template <class T>
struct is_pointer
{
  template <class U>
  static char is_ptr(U *); #1

  template <class X, class Y>
  static char is_ptr(Y X::*);

  template <class U>
  static char is_ptr(U (*)()); #2

  static double is_ptr(...);

  static T t;
  enum { value = sizeof(is_ptr(t)) == sizeof(char) };
};

To me, #2 is just a specialized version of #1, so it seems superfluous.

Did I make something wrong? What would it be like in the eyes of C++ compilers?


Solution

  • To me, #2 is just a specialization of #1, so it seems superfluous.

    An overload, not a specialization. And yes, it is superfluous. In a template accepting U* for a parameter, U can resolve to an entire function type. It's what makes is_pointer<int(*)(char)>::value be true, despite the fact int(*)(char) will not match the overload #2.

    Did I make something wrong?

    Since you did not make this code yourself, I don't believe you did. You correctly surmised there's a redundancy.

    What would it be like in the eyes of C++ compilers?

    It would be an overload that gets picked for the specific case of checking a function pointer type that accepts no arguments. It conveys no interesting information compared to the U* overload, and can be removed.

    It's possible this implementation was added to get around a compiler bug (where said function pointer types were not correctly handled). Modern compilers handle said function pointers correctly even if the superfluous overload is removed.