如何实例化成员函数指针?

时间:2016-11-20 14:02:01

标签: c++ c++14

假设我有以下代码

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


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

这段代码确实崩溃了,因为ptr是0.为什么成员函数构造函数返回0?

我的解决方法如下,但它涉及代码重复。没有其他方法可以从类型构造/实例化成员函数吗? C ++ 14欢迎。

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


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

4 个答案:

答案 0 :(得分:4)

  

为什么成员函数构造函数返回0?

因为它指针(-to-member-function)和所有标量类型值初始化为0(C ++ 14 [dcl.init] /8.4)。

  

没有其他方法可以从类型构造/实例化成员函数吗?

您可以拥有多个具有相同签名的成员函数;怎么知道你想引用哪个成员函数?

您拥有的代码适用于C ++ 14。在C ++ 17中,它可以缩短为以下内容:

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

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

答案 1 :(得分:1)

您无法从其类型中实例化成员函数。例如,请考虑以下类:

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

假设您有void (foo::*)(int)类型。您希望从中获得哪些功能?

从C ++ 1z开始,您将能够使用auto来推断非类型的非模板模板参数:

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


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

demo

我能想到的C ++ 11/14的唯一解决方法是使用宏:

#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

但出于可读性的原因,我建议不要使用它。

答案 2 :(得分:0)

decltype返回其参数的类型。使用以下示例:

class MyClass {

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

两个

decltype(&MyClass::foo);

decltype(&MyClass::bar);

的类型相同:int (MyClass::*)()

默认初始化此类型时,默认初始化结果为nullptr。因此崩溃。

答案 3 :(得分:0)

当你初始化一个指向成员函数的指针时,你当然会收到一个nullptr。

顺便说一句,您可以使用与Sam的答案中相同的类型具有多个成员函数。

我不知道为什么你需要将MemberFunc放到Foo的模板参数列表中。

但是,如果你想创建一个函数来调用它,这可能是C ++之前C ++中更好的方法(在C ++中使用auto 1z更能匹配这个问题):

class Foo {
  MyClass object_;
public:
  template<class MemberFunc>
  void call(MemberFunc ptr) {
    (object_.*ptr)();
  }
};
int main() {
  Foo foo;
  foo.call(&MyClass::doThings);
}