c++ - 如何从指向成员函数的指针推断出 `T` 的类型?

标签 c++ templates template-argument-deduction

我有一个模板,大致是这样的:

template<typename T,void (T::*F)()>
struct Foo{
    /* ... do some stuff with the member function pointer ...*/
    //... e.g.
    T foo(){
        T t;
        t.*F;
        return t;
};

它有效,但我不喜欢我必须实例化它的方式:

Foo<SomeVeryLongClassName,&SomeVeryLongClassName::AnEvenLongerMemberFunctionName> f;

有什么方法可以使模板推导出 T? 我在想一个我可以这样调用的模板方法:

getFoo(&SomeVeryLongClassName::AnEvenLongerMemberFunctionName);

或者,因为我将主要在 T 中使用 Foo,那只是

getFoo(AnEvenLongerMemberFunctionName);

我试过了

#include <iostream>

template <typename T,void (T::*MEMFUN)()>
struct Foo{};

template <typename T,void (T::*MEMFUN)()>
Foo<typename T,typename MEMFUN> getFoo(MEMFUN f){ 
     return Foo<typename T,typename MEMFUN>(); 
}


struct Bar { void test(){ std::cout << "MUH" << std::endl;} };

int main (){ getFoo(&Bar::test); }

错误信息其实很清楚,但是我完全看不懂...

templateExample.cpp:9:28: error: wrong number of template arguments (1, should be 2)
 Foo<typename T,typename MEMFUN>
                            ^
templateExample.cpp:4:8: error: provided for ‘template<class T, void (T::* MEMFUN)()> struct Foo’
 struct Foo{
        ^
templateExample.cpp:10:7: error: invalid type in declaration before ‘(’ token
 getFoo(MEMFUN f){
       ^
templateExample.cpp:10:7: error: template declaration of ‘int getFoo’
templateExample.cpp:10:15: error: expected ‘)’ before ‘f’
 getFoo(MEMFUN f){
               ^
templateExample.cpp: In function ‘int main()’:
templateExample.cpp:20:20: error: ‘getFoo’ was not declared in this scope
   getFoo(&Bar::test);

...为什么“模板参数的数量错误(1,应该是 2)”?

在实例化 Foo 时,如何帮助编译器推断出 T? 仅使用 C++11 之前的版本可能吗?

附言:this非常接近被骗,但我真的需要知道 T 的类型,而不仅仅是调用成员函数(例如,我需要创建一个实例)。

最佳答案

在 C++17 中,我们有带推导类型的非类型模板参数:

template <auto> struct Foo;

template <typename T, void (T::*MF)()> struct Foo<MF> {
  // ...
};

用法:Foo<&X::f>

也可以直接使用template <auto X>要么继续使用 auto在您的模板中或使用 decltype(X)获取非类型参数的类型。


在 C++17 之前,您可以尝试通过一些涉及带有成员函数模板的辅助类模板和 decltype 的扭曲来执行推导。 .

血淋淋的细节:

如果定义函数模板template <typename T, void(T::*MF)()> Foo<T, MF> f(MF); ,其中 Foo 是您的旧式类模板(如 template <typename T, void (T::*MF)()> class Foo; ),那么您可以使用 decltype(f(&X::h))推断出所需的类型 Foo<X, &X::h>而不必重复 X。代价是你要么需要说 decltype无处不在,或者您将其包装在宏中。

关于c++ - 如何从指向成员函数的指针推断出 `T` 的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43211811/

相关文章:

c++ - 如何在 mex 代码中表示 MATLAB 的二维数组

java - Apache 瓷砖 : how to access definition name

c++ - 使用带有 void 函数的模板

c++ - 模板非类型参数推导

c++ - 为什么这个初始化列表不能匹配模板参数?

c++ - 使用 strcmp() 比较两个 C 字符串数组

c++ - 如何合并多个点云构建3D map ?

c++ - 嵌套在类模板中的结构构造函数的问题

c++ - 为什么这两段代码给我不同的结果?