How to instantiate a member function pointer?

馋奶兔 提交于 2019-12-06 12:07:57

Why does the member function constructor returns 0?

Because it's a pointer (-to-member-function), and all scalar types value-initialize to 0 (C++14 [dcl.init]/8.4).

Is there no other way to just construct/instantiate the member function from the type?

You can have multiple member functions with the same signature; how would it know which member function you want to refer to?

The code you have is fine for C++14. In C++17, it can be shortened to the following:

template<auto f> 
class Foo {
  MyClass object_;
  void call() {
    (object_.*f)();
  }
};

int main() {
  Foo<&MyClass::doThings> foo;
  foo.call();
}

You can't instantiate a member function from its type. For example, consider the following class:

struct foo
{
    void bar(int){}
    void baz(int){}
};

Suppose you have a type void (foo::*)(int). Which function would you like to get from it?

As of C++1z, you'll be able to use auto to deduce non-type, non-template template parameters:

template<auto f> 
class Foo {
  MyClass object_;
  void call() {
    (object_.*f)();
  }
};


int main() {
  Foo<&MyClass::doThings> foo;
  foo.call();
}

demo


The only workaround for C++11/14 I can think of is using a macro:

#define type_value_pair(x) decltype(x), x
template<class MemberFunc, MemberFunc f> 
class Foo {
  MyClass object_;
  void call() {
    (object_.*f)();
  }
};


int main() {
  Foo<type_value_pair(&MyClass::doThings)> foo;
  foo.call();
}

demo

But I'd advise against using this, for readability reasons.

decltype returns the type of its argument. Using the following example:

class MyClass {

public:
    int foo();
    int bar();
};

Both

decltype(&MyClass::foo);

and

decltype(&MyClass::bar);

is the same type: int (MyClass::*)().

When you default-initialize this type, the default initialization results in a nullptr. Hence the crash.

When you value-initialize a pointer to member-function, you will receive a nullptr, of course.

By the way, you can have multiple member function with the same type as you can see in Sam's answer.

I don't know why do you need to put the MemberFunc to template parameter list of Foo.

However, if you want to make a function to call it, this maybe a better approach in C++ before C++1z (use auto in C++1z is better match for this question):

class Foo {
  MyClass object_;
public:
  template<class MemberFunc>
  void call(MemberFunc ptr) {
    (object_.*ptr)();
  }
};
int main() {
  Foo foo;
  foo.call(&MyClass::doThings);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!