2016-06-07 184 views
4

如何将模板指针指向成员函数?以模板非模板参数为函数模板

通过模板我的意思是以下类型事先不知道:

  • 模板PARAM T是类指针的成员
  • 模板PARAM R是返回类型
  • 可变参数模板PARAM Args...是参数

说明问题的非工作代码:

template <???> 
void pmf_tparam() {} 

// this works, but it's a function parameter, not a template parameter 
template <class T, typename R, typename... Args> 
void pmf_param(R (T::*pmf)(Args...)) {}  

struct A { 
    void f(int) {} 
}; 

int main() { 
    pmf_tparam<&A::f>(); // What I'm looking for 
    pmf_param(&A::f);  // This works but that's not what I'm looking for 
    return 0; 
} 

是否有可能在C++ 11中实现所需的行为?

+0

你需要这是一个真正的功能?我已经离开了C++游戏一段时间了,但是如果你让你的函数成为一个类并且重写'operator()'以便它看起来像一个函数一样工作呢? – Falmarri

回答

4

我不认为这个符号是可能的,但。有建议P0127R1使这个表示法成为可能。该模板将像这样声明:

template <auto P> void pmf_tparam(); 
// ... 
pmf_tparam<&S::member>(); 
pmf_tparam<&f>(); 

添加auto非类类型参数的建议被票选入C++工作文件Oulu,结果被评为成为CD通向C++ 17也在奥卢。没有auto类型的非类型参数,你需要提供指针的类型:

template <typename T, T P> void pmf_tparam(); 
// ... 
pmf_tparam<decltype(&S::member), &S::member>(); 
pmf_tparam<decltype(&f), &f>(); 
0

问题是不知道参数的类型,并希望该类型的模板参数。

有了一个额外的decltype(仍然在模板参数),这个工程:

#include <iostream> 
using namespace std; 

template <typename T, T ptr> 
void foo(){ 
    ptr(); 
} 

void noop() { 
    cout << "Hello" << endl; 
} 

int main() { 
    //Here have to use decltype first 
    foo<decltype(&noop), noop>(); 

    return 0; 
} 
1

正如你不是说你真的是在后的功能,最简单的是:

struct A { 
    void bar() { 
    } 
}; 

template <typename T> 
void foo() { 
    // Here T is void (A::*)() 
} 

int main(void) { 
    foo<decltype(&A::bar)>(); 
} 

但是如果你想要签名细分,我不知道有直接解决类型的一种方式,但是你可以用一点间接...

struct A { 
    void bar() { 
     std::cout << "Call A" << std::endl;  
    } 
}; 

template <typename R, typename C, typename... Args> 
struct composer { 
    using return_type = R; 
    using class_type = C; 
    using args_seq = std::tuple<Args...>; 
    using pf = R (C::*)(Args...); 
}; 

template <typename C, typename C::pf M> 
struct foo { 
    static_assert(std::is_same<C, composer<void, A>>::value, "not fp"); 

    typename C::return_type call(typename C::class_type& inst) { 
     return (inst.*M)(); 
    } 

    template <typename... Args> 
    typename C::return_type call(typename C::class_type& inst, Args&&... args) { 
     return (inst.*M)(std::forward<Args...>(args...)); 
    } 
}; 

template <class T, typename R, typename... Args> 
constexpr auto compute(R (T::*pmf)(Args...)) { 
    return composer<R, T, Args...>{}; 
} 

int main() { 
    foo<decltype(compute(&A::bar)), &A::bar> f; 
    A a; 
    f.call(a); 
} 

以上步骤S HOULD你是什么后...

1

你可以做的是

template <template T, T value> 
void pmf_tparam() {} 

然后

pmf_tparam<decltype(&A::f), &A::f>();