代码之家  ›  专栏  ›  技术社区  ›  ThreeStarProgrammer57

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

  •  2
  • ThreeStarProgrammer57  · 技术社区  · 8 年前

    我想将指向另一个模板成员函数的指针作为模板模板非类型参数传递给模板成员函数。

    以下是我尝试过的:

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

    我的语法错误,编译器说:

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

    我想不出正确的语法。

    LookupFunc 是类型的模板 Material * (Impl::*)(const Point&) 它是指向成员函数的指针。

    我想做的事可能吗?

    我错过了什么?

    2 回复  |  直到 8 年前
        1
  •  3
  •   n. m. could be an AI    8 年前

    下面是类模板作为functor的实现方法。

    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);
    }
    
        2
  •  3
  •   max66    8 年前

    正如注释中所解释的,没有指向模板函数(或方法)的单个指针,因为它不是一个函数,而是一组函数。

    我能想象的最好的方法是做类似的事情(我的意思是……解释 Unit 内部类型 GetMaterial() )就是在 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; }
        };
    

    然后重写 GetMaterial() 如下所示

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

    这样你就可以通过 GetMaterial() 单一类型( lm1 lm2 )包含全套模板函数;然后,在里面 GetMaterial() ,您可以选择正确的函数解释 Unit::model_unit

    下面是一个完整的工作示例

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