c++ 20概念:检查是否存在可变成员函数模板(或最佳实践替代方案)



是否可以对是否存在可变成员函数模板或是否存在一般成员函数模板进行概念检查?

背景:

我有一组类和类模板,可以对任意长度的值向量进行评估的数学函数建模。也就是说,给定这样一个函数f,你可以写

double y  = f(1.0, 2, 4.2);
double y2 = f(mathy_vector<3>{1.0, 2, 4.2});

以及其他一些运算,比如数学推导,这些运算实际上是整个问题的重点,但与这个特定的问题无关。这些函数是可组合的,例如,对于2 * x + y,可以有一个sum<product<constant, variable<0>>, variable<1>>

我希望有一个与这个函数接口相匹配的概念,以沿着

的行约束可组合类模板
template<mathy_function left_hand_side,
mathy_function right_hand_side>
class sum { ... };

SSCCE:

我要做的是:

#include <concepts>
template<int N>
struct mathy_vector { };
///////////////////
// Broken bit here
///////////////////
template<typename T>
concept mathy_function = requires(T f) {
// I would really like to test for a variadic op() here.
{ f(0.0) } -> std::same_as<double>;
{ f(1, 2, 3) } -> std::same_as<double>;
// I would also like to check for arbitrary N here
{ f(mathy_vector<100>{}) } -> std::same_as<double>;
};
///////////////////
// end of broken bit
///////////////////
struct dummy_function {
double operator()(std::convertible_to<double> auto&&...) const {
return 0.0;
}
template<int N>
double operator()(mathy_vector<N> const &v) const {
return 0.0;
}
};
template<mathy_function F>
void do_stuff(F const &f) { }
template<mathy_function LHS, mathy_function RHS>
struct sum { };
int main() {
dummy_function f;
do_stuff(f);
sum<dummy_function, dummy_function> sum_node;
}

这是一个合理的煤矿金丝雀编译,但当然,这个概念实际上是不正确的。有没有合适的方式来表达这个概念?

我有一种预感,它可能不是,因为我试图测试的具体可编译表达式的集合是无限的,所以我的后续问题是:如果这实际上是不可能的,那么应该做什么呢?现在,我让所有相关的类继承一个标记类型并对此进行测试,因此新表达式类型的开发人员必须显式地将其类型标记为兼容。这也是可用的,但不是很漂亮。

您的概念需要检查f是否使用正确数量的变量调用。例如,2 * x + y需要xy,而f可以用任意数量的参数调用。

让我们添加mathy_function具有成员类型variables的需求。

template<typename T, int... Is>
double call(T t, std::integer_sequence<int, Is...>)
{
return t(static_cast<double>(Is)...);
}
template<typename T>
concept mathy_function = requires(T f) {
{ T::variables::size() } -> std::same_as<std::size_t>
call(f, std::make_integer_sequence<int, T::variables::size()>{});
f(mathy_vector<T::variables::size()>{});
};

现在你也有了sum的东西来组合它来指定变量了

template<mathy_function lhs, mathy_function rhs>
class sum { 
using variables = decltype(boost::hana::union_(lhs::variables{}, rhs::variables{}));
double operator()(mathy_vector<variables::size()> v) { ... };
template <typename... Ts>
double operator()(Ts... ts) { return *this(mathy_vector{ ts... }); }
};

最新更新