2017-08-15 4 views
2

J'ai été cogner ma tête dans un mur pour les deux dernières heures à essayer de comprendre pourquoi certaines spécialisations de modèle partiel ne parviennent pas, et je ne pouvais vraiment utiliser un peu d'aide.C spécialisation partielle de ne fonctionne pas avec Diffère Taille Eigen Matrices

En fait, je travaille sur un code qui repose sur la connaissance des tailles de matrices au moment de la compilation, mais je suis en train de le faire avec des modèles génériquement. Il semble y avoir une sorte de problème avec l'utilisation de compositions de type que je ne comprends vraiment pas. A titre d'illustration, considérer les points suivants (un peu inutile) Code:

template <typename T> struct type1 { typedef bool bar; }; 
template <typename T, int R, int C> struct type1<Matrix<T, R, C>> { typedef Matrix<T, R, C> bar; }; 

template <typename T1, typename T2> struct type2 { typedef bool bar; }; 
template <typename T, int R, int M, int C> struct type2<Matrix<T, R, M>, Matrix<T, M, C>> { typedef Matrix<float, 2, 2> bar; }; 

template <typename T1, typename T2> struct type3 { typedef bool bar; }; 
template <typename T, int R, int M, int C> struct type3<Matrix<T, R, M>, Matrix<T, M, C>> { typedef Matrix<T, R, C> bar; }; 

template <typename T> struct Test { 
    static bool foo() { 
     return false; 
    } 
}; 
template <typename T, int R, int C> struct Test<Matrix<T, R, C>> { 
    static bool foo() { 
     return true; 
    } 
}; 

Ma compréhension de la composition du modèle est que ces modèles devraient pouvoir être composé de manière comme le ci-dessous où chaque ligne doit retourner vrai. Notez, cependant, que les deux derniers retournent faux.

/* true <- */ Test<Matrix<float, 2, 2>>::foo(); 
/* true <- */ Test<Matrix<float, 6, 3>>::foo(); 
/* true <- */ Test<type1<Matrix<float, 2, 7>>::bar>::foo(); 
/* And so on for any other size . . . */ 

/* true <- */ Test<type2<Matrix<float, 3, 3>, Matrix<float, 3, 3>>::bar>::foo(); 
/* true <- */ Test<type3<Matrix<float, 2, 2>, Matrix<float, 2, 2>>::bar>::foo(); 
/* And so on for any other pair of square sizes . . . */ 

/* false <- */ Test<type2<Matrix<float, 2, 3>, Matrix<float, 3, 2>>::bar>::foo(); 
/* false <- */ Test<type3<Matrix<float, 2, 4>, Matrix<float, 4, 1>>::bar>::foo(); 
/* And so on for any other pair of non-square sizes . . . */ 

Ce qui est particulièrement étrange est que quand je remplacerai Eigen::Matrix avec un template <typename T, int R, int C> struct Thing tout fonctionne arbitraire comme prévu (c.-à. Tous les tests de retour vrai), ce qui est la raison pour laquelle je pense que ce problème est spécifique à Eigen Matrices.


Modifier: En fait, cela semble être lié au fait que je construis sur MSVC (ne identiquement sur les 2015 et 2017). Quand je compile ceci sur g ++ ou sur clang, ça marche bien. Plus de preuves que Visual C++ est un vrai gâchis (pas que ce soit vraiment nécessaire).

En outre, il semble effectivement être lié à des cas où les deux paramètres ont des tailles différentes. Par exemple:

template <typename T1, typename T2> struct typetest { typedef bool bar; }; 
template <typename T, int R1, int C1, int R2, int C2> struct typetest<Matrix<T, R1, C1>, Matrix<T, R2, C2>> { typedef Matrix<float, 2, 2> bar; }; 

Ceci réussit lorsque les premier et deuxième types de matrices ont la même taille, mais échoue lorsqu'ils diffèrent. Par exemple:

/* true <- */ Test<typetest<Matrix<float, 2, 3>, Matrix<float, 2, 3>>::bar>::foo(); 
/* true <- */ Test<typetest<Matrix<float, 6, 1>, Matrix<float, 6, 1>>::bar>::foo(); 
/* false <- */ Test<typetest<Matrix<float, 2, 2>, Matrix<float, 2, 3>>::bar>::foo(); 
/* false <- */ Test<typetest<Matrix<float, 5, 3>, Matrix<float, 2, 4>>::bar>::foo(); 

Malheureusement, je suis coincé avec la plupart du temps MSVC pour le moment, en raison de certaines dépendances très ennuyeux, donc je besoin d'une solution de contournement. Quelqu'un a des idées?

+0

Tout fonctionne pour moi (pas de fausses valeurs) avec Eigen :: Matrix. Je peux donner une capture d'écran. – WindyFields

+0

J'ai utilisé le plus récent 3.3.4. – WindyFields

+0

Et le message d'erreur est? –

Répondre

0

Juste pour le rendre complet, la solution proposée par @chtz dans les commentaires ci-dessus fonctionne totalement avec MSVC 2015 et 2017. A titre d'exemple pour la question de différentes tailles spécifiques de la question, cela fonctionne parfaitement:

template <typename T1, typename T2> struct typen { typedef bool bar; }; 
template <typename T, int R, int M, int C, int O1, int O2, int Rc1, int Rc2, int Cc1, int Cc2> 
    struct typen<Matrix<T, R, M, O1, Rc1, Cc1>, Matrix<T, M, C, O2, Rc2, Cc2>> { typedef Matrix<T, R, C> bar; }; 
... 
/* true :-) */ Test<typen<Matrix<float, 2, 3>, Matrix<float, 3, 4>>::bar>::foo();