C++ 表示为结构的函数的部分求值

C++ 表示为结构的函数的部分求值,c++,templates,C++,Templates,为了允许自动微分,我将函数表示为结构 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)

为了允许自动微分,我将函数表示为结构

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.

或者类似的东西。

这里有一些语法糖开始

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

template<class T>
struct my_tag {};
注意使用了
operator()
而不是
eval
。接下来是一个模板变量:

template<GLuint i>
constexpr x_t<i> x = {};
而我们的一行添加:

template<class Lhs, class Rhs>
using add = op<Lhs, Rhs, std::plus<>>;
这给了我们一个很好的操作代数,使用起来不那么麻烦

auto f = x<0>+x<1>+x<2>;
如果我们想用它替换我们的
x
,我们只需要搜索并替换模板类型

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>;
};
模板
结构替换{using type=Target;}
模板
使用replace\u t=typename replace::type;
模板
结构替换{
使用类型=结果;
};
模板
结构替换{
使用类型=Z;
};
replace_t
将用
f
表达式树中的常量
pi_constant
替换
x
的所有实例

自然地,
pi_常量的值必须在编译时已知


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

老实说,我尝试过,但我不知道您想做什么,也不知道问题出在哪里。现在,所需的语法类似于
ae::eval(ptr)
。请详细说明这有什么问题,以及您希望它变成什么样子。这不能使用
constexpr
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) );
  }
};
template<class Lhs, class Rhs>
using add = op<Lhs, Rhs, std::plus<>>;
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; }
};
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>;
};