vsoftco - 1 year ago 75

C++ Question

I am trying (and failing) to write a type trait that detects Eigen expressions. In other words, I'd like to be able to detect things like

`A * A + B`

`A`

`B`

`Eigen`

`template<typename T>`

struct is_matrix_expression : std::false_type

{

};

template<typename Derived> // specialization

struct is_matrix_expression<Eigen::MatrixBase<Derived>> :

std::true_type

{

};

Note that

`Eigen::MatrixBase<Derived>`

`decltype(A * A + B)`

`decltype(A * A + B)`

`MatrixBase<Derived>`

How can I somehow enforce the specialization to be picked out? Or, in other words, enable the specialization for all possible children of

`Eigen::MatrixBase<Derived>`

`std::is_base_of`

`Derived`

Equivalently, how can I detect whether a type

`X`

`Base<T>`

`T`

Answer Source

This detects if something inherits from `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 >;
```

C++20 has `is_detected`

which is similar to `can_apply`

above.

`std::void_t`

is C++14, but easy to write in C++11.

To read the above in english:

`is_bob<T>`

is true if and only if you can invoke `is_bob_r<T>`

.

`is_bob_r`

can be invoked if `is_bob_f( T const& )`

is a valid call.

`is_bob_f`

has an overload for `is_bob_f( bob_template<T> const& )`

only.

`can_apply<Z, T>`

is (derived from) `true_type`

if `Z<T>`

is valid, and (derived from) `false_type`

otherwise.

So `is_bob<T>`

is true if and only if `T`

can be deduced into `bob_template<U>`

for some `U`

. Which basically means `bob_template<U>`

is a (public) base class of `T`

.