编写一个类型特征来检测特征中的矩阵表达式

vso*_*tco 2 c++ templates type-traits eigen c++11

我正在尝试(并且失败)写一个检测特征表达式的类型特征.换句话说,我想能够检测之类的东西A * A + B等,其中ABEigen矩阵/向量.目前我这样做:

template<typename T>
struct is_matrix_expression : std::false_type
{
};

template<typename Derived> // specialization
struct is_matrix_expression<Eigen::MatrixBase<Derived>> :
        std::true_type
{
};
Run Code Online (Sandbox Code Playgroud)

注意,它Eigen::MatrixBase<Derived>是所有可能的特征表达式(例如decltype(A * A + B)等)的(模板)基础.然而,正在挑选一般模板,因为它更适合类似的东西decltype(A * A + B),而不是MatrixBase<Derived>专业化.

我怎样才能以某种方式强制执行专业化?或者,换句话说,为所有可能的孩子启用专业化Eigen::MatrixBase<Derived>?我在SFINAE上打了一些std::is_base_of,但这需要一个显式类型,而不是一个模板,其中表达式的类型(在这种情况下Derived)是事先不知道的.

同样,对于某些类型,我如何检测某个类型X是否为子Base<T>T

Yak*_*ont 6

这会检测某些内容是否继承自bob_template<T>:

template<class T>
struct bob_template {};

template<class T>
constexpr std::true_type is_bob_f( bob_template<T> const& ) { return {}; }

namespace details {
    template<template<class...>class Z, class, class...Ts>
    struct can_apply:std::false_type{};
    template<template<class...>class Z, class...Ts>
    struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z, void, Ts...>;

template<class T>
using is_bob_r = decltype( is_bob_f( std::declval<T const&>() ) );

template<class T>
using is_bob = can_apply< is_bob_r, T >;
Run Code Online (Sandbox Code Playgroud)

实例.

C++ 20具有is_detectedcan_apply上面类似的内容.

std::void_t 是C++ 14,但很容易用C++ 11编写.

用英语阅读以上内容:

is_bob<T>当且仅当您可以调用时才是真的is_bob_r<T>.

is_bob_r如果is_bob_f( T const& )是有效的调用,则可以调用.

is_bob_fis_bob_f( bob_template<T> const& )只有过载.

can_apply<Z, T>是(派生自)true_typeif Z<T>是否有效,以及(派生自)false_type否则.

所以,is_bob<T>当且仅当是真的T可以推断到bob_template<U>一些U.这基本上意味着bob_template<U>(公共)基类T.


dav*_*igh 5

这里应该做这样的事情:

template<typename Derived>
struct is_matrix_expression
 : std::is_base_of<Eigen::MatrixBase<std::decay_t<Derived> >, std::decay_t<Derived> >
{};
Run Code Online (Sandbox Code Playgroud)

对于以下代码段,它打印 true:

Eigen::MatrixXd A, B;
std::cout<< is_matrix_expression <decltype(A*A + B)>::value <<std::endl;   //true
std::cout<< is_matrix_expression <int>::value <<std::endl;                 //false
Run Code Online (Sandbox Code Playgroud)

想法是,在这里您知道基类是什么样子:即,对于SomeMatrixXpr,它将MatrixBase<SomeMatrixXpr>根据Eigen 类层次结构。这与 @Yakk 的方法相反,@Yakk 的方法适用于任何类型的基类(甚至是那些与 CRTP 不相关的基类)。