【问题标题】:Function template taking a template non-type template parameter函数模板采用模板非类型模板参数
【发布时间】:2016-06-07 23:00:23
【问题描述】:

如何将模板化指针指向成员函数?

我所说的模板化是指事先不知道以下类型:

  • 模板参数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 中实现所需的行为?

【问题讨论】:

  • 您需要这是一个真正的功能吗?我已经有一段时间没有接触 C++ 游戏了,但是如果你将你的函数设为一个类并重写 operator() 使其看起来和工作起来像一个函数呢?

标签: c++ templates c++11


【解决方案1】:

我不认为这种表示法是可能的。有提议 P0127R1 使这个符号成为可能。模板将被声明为:

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

为非类型类型参数添加auto 的提案在Oulu 的C++ 工作论文中被投票通过,结果被投票成为CD 在奥卢也通往C++17。如果非类型参数没有 auto 类型,则需要提供指针的类型:

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

【讨论】:

    【解决方案2】:

    由于你没有在函数中真正说出你想要什么,最简单的是:

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

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

    【讨论】:

      【解决方案3】:

      你能做的是

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

      然后

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

      【讨论】:

        【解决方案4】:

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

        加上一个额外的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;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-03
          • 1970-01-01
          相关资源
          最近更新 更多