采用模板非类型模板参数的函数模板

Function template taking a template non-type template parameter

本文关键字:函数模板 参数 类型      更新时间:2023-10-16

如何获取指向成员函数的模板化指针?

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

  • 模板参数T是指向成员的指针的类
  • 模板参数R是返回类型
  • 可变参数模板
  • 参数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 中实现所需的行为?

我认为这种符号还是不可能的。有人提议P0127R1使这种表示法成为可能。模板将被声明为如下所示的内容:

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

为非类型类型参数增加auto的提案在奥卢的C++工作文件中被投票表决,结果在奥卢也投票成为导致C++17的CD。如果没有非类型参数的auto类型,则需要提供指针的类型:

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

由于您还没有真正说明您在函数中追求什么,最简单的是:

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);
}

以上应该做你所追求的...

你能做的是

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

然后

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

问题是不知道参数的类型并想要该类型的模板参数。

使用额外的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;
}