部分评估表示为结构的函数

时间:2015-08-17 21:21:23

标签: c++ templates

为了允许自动区分,我将函数表示为struct

template <GLuint i>
struct x 
{
   static GLfloat eval (const GLfloat * o)
   {
      return o [i];
   }
};

template <typename A, typename B>
struct ae
{
   static GLfloat eval (const GLfloat * o) {return A :: eval (o) + B :: eval (o);}
};

etc.

其中x <i>表示参数。

但是,因为我需要

  1. 在开头用常量替换一些参数
  2. x <i>区分时,将剩余参数设置为常量值
  3. 我应该如何实现部分评估,以便可以避免重复传递常量参数,并相应地简化函数结构?

    修改

    我们有一个功能

    typedef ae <x <0>, ae <x <1>, x <2>>> f
    

    我知道x <1>x <2>c <1>c <2>)的值。 现在我想将f转换为typedef ae <x <0>, c> F

    struct c
    {
       static GLfloat eval (const GLfloat * o) {return c <1> + c <2>;}
    };
    

    或类似的东西。

1 个答案:

答案 0 :(得分:3)

这是一些开始的语法糖。

这是CRTP标记类型。给它一个更好的名字:

template<class T>
struct my_tag {};

参与此游戏的每种类型都应继承my_tag<themselves>

接下来是x

template<GLuint i>
struct x_t : my_tag<x_t<i>> {
  GLfloat operator()(const GLfloat * o) const {
    return o[i];
  }
};

请注意使用operator()代替eval。接下来是模板变量:

template<GLuint i>
constexpr x_t<i> x = {};

我们可能需要将constexpr x_t() {}添加到x_t,具体取决于您的编译器。

这是一项通用操作:

template<class Lhs, class Rhs, class Op>
struct op : my_tag<op<Lhs, Rhs, Op>> {
  GLfloat operator()(const GLfloat* o) const {
    return Op{}( Lhs{}(o), Rhs{}(o) );
  }
};

和我们的一行add

template<class Lhs, class Rhs>
using add = op<Lhs, Rhs, std::plus<>>;

在C ++ 11中,我们必须编写std::plus<void>。在C ++ 03中,替换使用with而不是struct add:op<Lhs,Rhs,std::plus<>>{};(并自己编写plus<>)。

现在,我们会对标有operator+的内容覆盖my_tag

template<class Lhs, class Rhs>
add<Lhs, Rhs> operator+( my_tag<Lhs>, my_tag<Rhs> ) { return {}; }

这为我们提供了一个很好的代数操作,使用起来不那么尴尬。

auto f = x<0>+x<1>+x<2>;

或者,如果我们想要类型

decltype(x<0>+x<1>+x<2>) f;

...好吧,我刚刚清理了你的系统。

下一个游戏是用常量替换变量。

struct pi_constant {
  constexpr GLfloat operator()(const GLfloat*)const { return 3.14; }
};

如果我们想用x<i>替换它,我们只需要搜索并替换模板类型。

template<class Target, class Pattern, class Result>
struct replace { using type=Target; }
template<class Target, class Pattern, class Result>
using replace_t = typename replace<Target, Pattern, Result>::type;

template<class Pattern, class Result>
struct replace<Pattern, Pattern, Result>{
  using type=Result;
};

template<template<class...>class Z, class...Ts, class Pattern, class Result>
struct replace<Z<Ts...>, Pattern, Result>{
  using type=Z<replace_t<Ts, Pattern, Result>..., Pattern, Result>;
};

replace_t< decltype(f), x_t<1>, pi_constant >会将x<1>的所有实例替换为pi_constant的表达式树中的常量f

当然,pi_constant的值必须在编译时知道。

...

现在,如果您在编译时不知道这些值,一种方法可能是让您的变量不是一个,而是两个数组。然后你可以使用上面的替代技巧来交换你正在阅读的两个数组中的哪一个。