2016-10-27 6 views
2

Ich versuche (und scheitere), eine Typeigenschaft zu schreiben, die Eigenausdrücke erkennt. Mit anderen Worten, ich möchte in der Lage sein, Dinge wie A * A + B usw. zu erkennen, wobei A und BEigen Matrizen/Vektoren sind. Zur Zeit mache ich das:Schreiben eines Typenmerkmals zum Erkennen von Matrixausdrücken in 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 
{ 
}; 

Beachten Sie, dass Eigen::MatrixBase<Derived> ist eine (Schablone) Basis für alle möglichen Eigen Ausdrücke (wie decltype(A * A + B) usw.). Die allgemeine Vorlage wird jedoch ausgewählt, da sie besser für etwas wie decltype(A * A + B) und nicht für die Spezialisierung MatrixBase<Derived> geeignet ist.

Wie kann ich irgendwie die Spezialisierung erzwingen? Oder, mit anderen Worten, aktivieren Sie die Spezialisierung für alle möglichen Kinder von Eigen::MatrixBase<Derived>? Ich habe ein wenig mit SFINAE unter std::is_base_of gespielt, aber das erfordert einen expliziten Typ und keine Vorlage, bei der der Typ des Ausdrucks (in diesem Fall Derived) nicht im Voraus bekannt ist. Wie kann ich erkennen, ob ein Typ X ein Kind von Base<T> ist, für einen Typ T? Diese

+0

Drop that 'typename'. Schreibst du 'typenname std :: template vector '? –

+0

Ist [diese alte Antwort] (http://stackoverflow.com/a/12182195/27678) hilfreich? – AndyG

+0

Ich denke, dein Problem ist, dass 'declltype (A * A + B)' nicht 'MatrixBase '... es wird wie' CwiseBinaryOp 'Recht sein? – Barry

Antwort

5

erkennt, wenn etwas erbt von 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 hat is_detected, die can_apply oben ähnlich ist.

std::void_t ist C++ 14, aber einfach in C++ 11 zu schreiben.

Um die oben in Englisch zu lesen:

is_bob<T> wahr ist, wenn und nur wenn Sie is_bob_r<T> aufrufen kann.

is_bob_r kann aufgerufen werden, wenn is_bob_f(T const&) ein gültiger Aufruf ist.

is_bob_f hat nur eine Überlastung für is_bob_f(bob_template<T> const&).

can_apply<Z, T> ist (abgeleitet von) true_type, wenn Z<T> gültig ist, und (abgeleitet von) false_type andernfalls.

Also is_bob<T> ist wahr, wenn und nur wenn T in bob_template<U> für einige U abgeleitet werden kann. Was im Grunde bedeutet bob_template<U> ist eine (öffentliche) Basisklasse von T.

+0

Das ist sehr nett und generisch! – vsoftco

4

So etwas wie hier sollte dies tun:

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

Es ist für das folgende Stück Code wahr druckt:

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 

Idee ist, dass hier wissen Sie, was die Basisklasse wie folgt aussieht: nämlich, für SomeMatrixXpr wird es MatrixBase<SomeMatrixXpr> entsprechend der Eigen class hierarchy sein.Dies steht im Gegensatz zu dem Ansatz von @ Yakk, der für jede Art von Basisklassen (auch solche, die nicht mit CRTP verwandt sind) funktioniert.

+0

Das macht es auch! – vsoftco

+0

@vsoftco: danke, ich habe einen Schnitt gemacht [warum] (https://eigen.tuxfamily.org/dox/TopicClassHierarchy.html) – davidhigh

+0

Sie vermissen einen 'typename', denke ich? Aber eigentlich solltest du einfach den ':: type' am Ende von' is_base_of' abrasieren; Erben ist gut genug. – Yakk

Verwandte Themen