dynamic algorithm
template <class T, class = void>
struct has_initialize : std::false_type
{
};
template <class T>
struct has_initialize<T, std::void_t<decltype(&T::initialize)>> : std::true_type
{
};
template <class T, class = void>
struct has_interaction : std::false_type
{
};
template <class T>
struct has_interaction<T, std::void_t<decltype(&T::interaction)>> : std::true_type
{
};
template <class T, class = void>
struct has_update : std::false_type
{
};
template <class T>
struct has_update<T, std::void_t<decltype(&T::update)>> : std::true_type
{
};这些代码的作用是检查一个类是否具有initialize、interaction或update成员函数。以has_initialize为例。第一个模板的模板参数是T和一个匿名参数,匿名参数的默认值是void。它继承于std::false_type,这个类有一个value成员,值为false。
第二个模板采用了部分特例化(偏特化)。第一个模板参数仍为T,第二个模板参数很有意思,首先通过&T::initialize获取T类initialize成员函数的地址。decltype(&T::initialize)获取了该地址的类型。std::void_t<...>是一个模板元编程工具,它接受任意数量的类型参数,并总是映射(定义)为 void类型。它的妙处在于:如果 decltype内部的表达式(&T::initialize)是无效的(即 T没有 initialize成员),那么替换 std::void_t的模板参数就会失败。根据SFINAE(Substitution Failure Is Not An Error)原则,这个失败不会导致编译错误,编译器只会简单地忽略这个偏特化版本,转而使用主模板。如果表达式有效,那么 std::void_t<...>就是 void类型,并且此类继承于std::true_type。std::true_type的value成员是true。
使用方式如下:
如果LocalDynamicsType有initialize成员函数或者interaction成员函数,就会使得断言失败。这意味着SimpleDynamics的LocalDynamicsType模板参数不能有initialize成员函数或者interaction成员函数,只能有update成员函数。
Last updated