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