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

时间:2016-10-27 19:47:25

标签: c++ c++11 templates eigen typetraits

我正在尝试(并且失败)写一个检测特征表达式的类型特征。换句话说,我希望能够检测到//var x_client = 0; //var y_client = 0; var battlefield_client = ""; var setColor=''; function colorSelect (){ colorPick = event.target || event.srcElement; colorPick = colorPick.id; console.log(colorPick); if (colorPick == redButton) { setColor = "red"; } else if (colorPick == orangeButton) { setColor = "orange"; } else if (colorPick == yellowButton) { setColor = "yellow"; } else if (colorPick == greenButton) { setColor = "green"; } else if (colorPick == blueButton) { setColor = "blue"; } else if (colorPick == violetButton) { setColor = "purple"; } else if (colorPick == brownButton) { setColor = "brown"; } else if (colorPick == blackButton) { setColor = "black"; } console.log(setColor); } //---end of colorSelect function placeBoat_client () { var demoColor = "orange"; var source_client = event.target.id; console.log(source_client); source_client.id = document.getElementById(source_client.id); document.getElementById(source_client).style.backgroundColor = demoColor; } for (var y_client = 1; y_client < 11; y_client++) { battlefield_client += "<tr>"; for (var x_client = 1; x_client < 11; x_client++) { battlefield_client += "<td onclick = '' class = 'tile' style='border: 3px solid black;' id=" + "cell_client_" + x_client + "_" + y_client + "><pre> </pre></td>"; } battlefield_client += "</tr>"; } $(document).ready(function() { $("#tableGrid_client").html(battlefield_client); //loads table for (var y_client = 1; y_client < 11; y_client++) { for (var x_client = 1; x_client < 11; x_client++) { boatStatusClient = document.getElementById('cell_client_' + x_client + "_" + y_client); boatStatusClient.addEventListener("click", /*boatGrid.*/placeBoat_client, false); } } document.getElementById("redButton").addEventListener("click", /*boatGrid.*/colorSelect, false); document.getElementById("orangeButton").addEventListener("click", /*boatGrid.*/colorSelect, false); document.getElementById("yellowButton").addEventListener("click", /*boatGrid.*/colorSelect, false); document.getElementById("greenButton").addEventListener("click", /*boatGrid.*/colorSelect, false); document.getElementById("blueButton").addEventListener("click", /*boatGrid.*/colorSelect, false); document.getElementById("violetButton").addEventListener("click", /*boatGrid.*/colorSelect, false); document.getElementById("brownButton").addEventListener("click", /*boatGrid.*/colorSelect, false); document.getElementById("blackButton").addEventListener("click", /*boatGrid.*/colorSelect, false); }); //end of ready 等内容,其中A * A + BAB矩阵/向量。目前我正在这样做:

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 { }; 是所有可能的特征表达式(例如Eigen::MatrixBase<Derived>等)的(模板)基础。但是,正在挑选一般模板,因为它更适合decltype(A * A + B)之类的内容,而不是decltype(A * A + B)专业化。

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

同样,对于某些类型Derived,我如何检测某个类型XBase<T>的孩子?

2 个答案:

答案 0 :(得分: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 >;

live example

C ++ 20有is_detected,类似于上面的can_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_f只有is_bob_f( bob_template<T> const& )的重载。

如果can_apply<Z, T>有效,则

true_type(来自)Z<T>,否则来自false_type

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

答案 1 :(得分:4)

这样的事情应该做:

template<typename Derived>
struct is_matrix_expression
 : std::is_base_of<Eigen::MatrixBase<std::decay_t<Derived> >, std::decay_t<Derived> >
{};

对于以下代码,它打印为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

想法就是在这里你知道基类是什么样的:对于SomeMatrixXpr,根据Eigen class hierarchy,它将是MatrixBase<SomeMatrixXpr>。这与@ Yakk的方法形成对比,后者适用于任何类型的基类(即使是那些与CRTP无关的基类)。