获取与模板arg中传递的函数成员类型相同的类

时间:2018-02-03 19:43:47

标签: c++ templates function-pointers

我正在尝试但是当我将派生类的函数成员指针作为模板参数传递时,我不知道如何(但可能不可能)捕获相同的类型类。

例如,拥有这段代码,

class CObject{

public:
    string m_id;

    void setID(const char * id){
        printf("assign id %s\n",id);
        m_id=string(id);
    }

     ~CObject(){}
};


class CDerivedObject:public CObject{
public:
    ~CDerivedObject(){};
};

使用此功能模板,

template < typename _R, class _T, typename..._A>
void function_template_test(_R (_T:: *function_type)(_A...) )
{

    printf("ObjectTypeIs: %s\n",typeid( _T).name());
}

在main函数中我调用function_template_test传递函数指针成员CDerivedObject :: setID,

function_template_test(&CDerivedObject::setID);

如果我使用g ++编译此代码(我的上一个版本是5.4.0),则打印 7CObject ,这意味着_T是CObject类型,但在参数中我传递了 CDerivedObject :: setID。我知道函数setID函数属于CObject,因此编译器会以这种方式获取类型,但是......

有没有办法捕获我传递模板参数的类类型(即_T是CDerivedObject)?

编辑1

我的问题的解决方案可能是这个,

template < class _C, class _R, typename _T, typename..._A>
void _function_template_test(_R (_T:: *function_type)(_A...) )
{

    printf("ObjectTypeIs: %s\n",typeid( _C).name());
}

#define function_template_test(cl, fun)\
        _function_template_test<cl>(&cl::fun)

然后我将该函数称为

function_template_test(CDerivedObject,setID);

是一个解决方案,但我更喜欢模板而不是宏。

1 个答案:

答案 0 :(得分:2)

考虑这个程序:

struct Base { void foo() {} };
struct Derived: Base {};

auto main() -> int
{
    int x = &Derived::foo;
}

这是使用MinGW g ++进行编译的结果:

[H:\forums\so\056]
> g++ main.cpp
main.cpp: In function 'int main()':
main.cpp:6:23: error: cannot convert 'void (Base::*)()' to 'int' in initialization
     int x = &Derived::foo;
                       ^~~

[H:\forums\so\056]
> _

正如您所看到的,&Derived::foo的类型是void (Base::*)()(是的,根据标准,这是

)。

即,当你问

  

是否有可能捕获类型I&m;传递模板参数的方法

......这就是你正在做的事情。

要使该类型为void (Derived::*)(),您需要在Derived中声明一个函数。

对于调用带有成员函数指针的函数的情况,您也可以显式指定所有模板参数。这是有效的,因为void (Base::*)()会隐式转换为void (Derived::*)()。是的,这是违反直觉的,并且在C ++类型系统中构成了一个小小的漏洞,但是当您考虑可以调用成员函数的类型对象时,它就是逻辑运行的方式。

重新开环,这是一个例子(见ma,没有演员表!):

#include <iostream>
#include <stack>
using namespace std;

auto main()
    -> int
{
    stack<int> st;
    for( int const i : {1, 2, 3} ) { st.push( i ); }

    struct Hack: stack<int> { using stack<int>::c; };
    int const n = (st.*&Hack::c).size();
    cout << "That stack contains " << n << " items." << endl;
}