2016-10-27 2 views
2

고유 표현식을 탐지하는 유형 특성을 작성하려고합니다. 즉, A * A + B 등을 감지 할 수 있기를 원합니다. 여기서 ABEigen 행렬/벡터입니다. 현재 내가이 일을 해요 : Eigen::MatrixBase<Derived> 가능한 모든 아이겐 식의 (템플릿) 기지 (예 : decltype(A * 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 
{ 
}; 

하는 것으로. 그러나 MatrixBase<Derived> 전문화가 아닌 decltype(A * A + B)과 같은 것이 더 적합하기 때문에 일반 템플릿이 선택됩니다.

필자는 어떻게 전문성을 고를 수 있습니까? 또는 다른 말로하면 Eigen::MatrixBase<Derived>의 가능한 모든 어린이를 전문화 할 수 있습니까? 나는 std::is_base_of에 SFINAE와 조금 놀았지만, 표현식의 유형 (이 경우 Derived)이 미리 알려지지 않은 템플릿이 아닌 명시적인 유형이 필요합니다.

동등하게 유형 XBase<T>의 자식인지 여부를 감지 할 수 있습니까? 일부 유형은 T입니까? 뭔가 bob_template<T>에서 상속하는 경우

+0

'typename'을 삭제하십시오. 'typename std :: template vector '이라고 쓰시나요? –

+0

[이 이전 답변] (http://stackoverflow.com/a/12182195/27678)이 도움이 되었습니까? – AndyG

+0

당신의 문제는'decltype (A * A + B)'가'MatrixBase '이 아니라고 생각합니다. 그것은'CwiseBinaryOp '와 같을 것 같습니까? – Barry

답변

5

이 감지 :

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_r<T>를 호출 할 수있는 경우에만 경우

is_bob<T>는 사실이다. is_bob_f(T const&)이 유효한 호출 인 경우

is_bob_r을 호출 할 수 있습니다.

is_bob_fis_bob_f(bob_template<T> const&)에 대해서만 과부하가 있습니다.

can_apply<Z, T>Z<T>이 유효한 경우 true_type이고, 그렇지 않은 경우 false_type 인 경우 (파생 된).

그래서 TU 일 경우 bob_template<U>으로 추론 될 수있는 경우에만 is_bob<T>이 참입니다. 기본적으로 bob_template<U>은 (공개) 기본 클래스 T입니다. 여기에이 같은

+0

아주 훌륭하고 일반적인 것입니다! – vsoftco

4

뭔가 수행해야합니다

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 

아이디어는 기본 클래스가 어떻게 생겼는지 여기에 있다는 것입니다 : 그것은 다음의 코드 조각에 대해 true를 인쇄

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

즉, SomeMatrixXpr의 경우 Eigen class hierarchy에 따라 MatrixBase<SomeMatrixXpr>이됩니다.이는 @ Yakk의 접근 방식과는 달리 모든 유형의 Base 클래스 (CRTP와 관련없는 클래스도 포함)에서 작동합니다.

+0

이것도 마찬가지입니다! – vsoftco

+0

@vsoftco : 감사합니다. [why] (https://eigen.tuxfamily.org/dox/TopicClassHierarchy.html)를 편집했습니다. – davidhigh

+0

'typename'이 누락되었습니다. 그러나 정말로'is_base_of'의 끝에서':: type'을 면도해야합니다. 상속은 충분합니다. – Yakk

관련 문제