3

Why do I need a * to make checker as pointer on line

template <typename C> static yes test( checker<C, &C::helloworld>* );

for the compile time deductions to work correctly, outputting 1 0?

When I remove the *, the output is 0 0

#include <iostream>

struct Generic {}; 
struct Hello
{ int helloworld() { return 0; } };

// SFINAE test
template <typename T>
class has_helloworld
{
    typedef char                yes;
    typedef struct {char _[2];}  no; 

    template <typename C, int (C::*)()> struct checker;

    template <typename C> static yes test( checker<C, &C::helloworld>* );
    template <typename C> static no  test(...);

public:
    enum { value = sizeof(test<T>(0)) == sizeof(yes) };
};

int main(int argc, char *argv[])
{
    std::cout << has_helloworld<Hello>::value   << std::endl;
    std::cout << has_helloworld<Generic>::value << std::endl;
    return 0;
}

This was an exercise from me trying to put together these two posts:

Is it possible to write a template to check for a function's existence?

Check if a class has a member function of a given signature

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Seoul
  • 585
  • 1
  • 4
  • 14

1 Answers1

5

Because it's called as test<T>(0), and 0 could be accepted as a null pointer if test takes a pointer as parameter type (as checker<C, &C::helloworld>*).

If you remove * to make the parameter type to checker<C, &C::helloworld>, test<T>(0) could only match test(...) then you'll always get the result 0.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405