简体   繁体   English

如何传递模板模板非类型成员函数指针?

[英]How to pass a template template non-type member function pointer?

I would like to pass (to a template member function) a pointer to a another template member function as a template template non-type parameter. 我想将(另一个模板成员函数的)指针作为模板模板非类型参数传递给模板成员函数。

Here is what I've tried: 这是我尝试过的:

enum Unit { model_unit, nanometers, meters };

struct Material {
     double rho;
};

struct Point {
    double x, y, z;
};

struct Impl{

    template<Unit unit>
    Material * LookupMat_1(const Point& p) {
        return nullptr; // let's suppose it returns a valid pointer
    }

    template<Unit unit>
    Material * LookupMat_2(const Point& p) {
        return nullptr; // let's suppose it returns a valid pointer
    }

    // compiler error here:
    // expected 'class' or 'typename' before 'Material'
    // template<template<Unit> Material * (Impl::*LookupFunc)(const Point&)
    //                         ^~~~~~~~
    template<template<Unit> Material * (Impl::*LookupFunc)(const Point&) >
    Material * GetMaterial(const Point & p) {

        return (this->*LookupFunc<Unit::model_unit>)(p);
    }

    void DoSomething() {

        Point p = {};

        auto mat_1 = GetMaterial<LookupMat_1>(p);
        auto mat_2 = GetMaterial<LookupMat_2>(p);
    }
};

int main() {

    Impl i;

    i.DoSomething();

}

My syntax is wrong, the compiler says: 我的语法错误,编译器说:

 main.cpp:25:29: error: expected 'class' or 'typename' before 'Material' template<template<Unit> Material * (Impl::*LookupFunc)(const Point&) ^~~~~~~~ 

I cannot figure out the right syntax. 我找不到正确的语法。

LookupFunc is a template of type Material * (Impl::*)(const Point&) which is a pointer to a member fonction. LookupFunc是类型Material * (Impl::*)(const Point&)的模板,该模板是指向成员Material * (Impl::*)(const Point&)的指针。

Is what I am trying to do possible? 我想做的事可能吗?

What am I missing? 我想念什么?

As explained in comments, there isn't a single pointer to a template function (or method) because isn't a function but a set of functions. 如注释中所述,没有一个指向模板函数(或方法)的指针,因为它不是函数,而是一组函数。

The best I can imagine to do something similar (I mean... explicating the Unit type inside GetMaterial() ) is to add a couple of sub-structs in Impl with static template methods 我能想到的做类似事情的最好方法(我的意思是……在GetMaterial() Unit类型)是使用静态模板方法在Impl添加几个子结构。

   struct lm1
    {
      template <Unit U>
      static Material * func (Point const & p)
       { return nullptr; }
    };

   struct lm2
    {
      template <Unit U>
      static Material * func (Point const & p)
       { return nullptr; }
    };

then rewrite GetMaterial() as follows 然后如下重写GetMaterial()

template <typename T>
Material * GetMaterial (Point const & p)
 { return T::template func<Unit::model_unit>(p); }

and use it this way 并以这种方式使用

void DoSomething()
 {
   Point p = {};

   auto mat_1 = GetMaterial<lm1>(p);
   auto mat_2 = GetMaterial<lm2>(p);
 }

This way you pass to GetMaterial() a single type ( lm1 or lm2 ) that contains the full set of template functions; 这样,您将包含完整模板功能集的单一类型( lm1lm2 )传递给GetMaterial() then, inside GetMaterial() , you select the right function explicating Unit::model_unit . 然后,在GetMaterial() ,选择正确的函数来Unit::model_unit

The following is a full working example 以下是完整的工作示例

enum Unit { model_unit, nanometers, meters };

struct Material
 { double rho; };

struct Point
 { double x, y, z; };

struct Impl
 {
   struct lm1
    {
      template <Unit U>
      static Material * func (Point const & p)
       { return nullptr; }
    };

   struct lm2
    {
      template <Unit U>
      static Material * func (Point const & p)
       { return nullptr; }
    };


   template <typename T>
   Material * GetMaterial (Point const & p)
    { return T::template func<Unit::model_unit>(p); }

   void DoSomething()
    {
      Point p = {};

      auto mat_1 = GetMaterial<lm1>(p);
      auto mat_2 = GetMaterial<lm2>(p);
    }
 };

int main ()
 {
   Impl i;

   i.DoSomething();
 }

Here's the class-template-as-functor way of doing this. 这是将类模板用作函数的方法。

template<Unit unit>
struct LookupMat_1
{
   Material * operator()(const Point& p) {
       return nullptr;
   }
};

template<Unit unit>
struct LookupMat_2
{
   Material * operator()(const Point& p) {
       return nullptr;
   }
};

template<template<Unit> typename LookupMat>
Material * GetMaterial(const Point & p)
{
    return LookupMat<Unit::model_unit>()(p);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM