2017-06-05 2 views
0

J'ai une fonction basé sur un modèle, qui devrait générer une taille fixe connue compilation vecteur, en fonction du paramètre du modèle:Eigen Bibliothèque: Assertions a échoué dans un modèle

template <int nSize> 
Eigen::Matrix<double, nSize, 1> myFunc() 
{ 
    switch(nSize){ 
    case 2: return ExternalLibrary::generate_Vector_2d(); 
    case 3: return ExternalLibrary::generate_Vector_3d(); 
    } 
} 

Cependant, quand je compile ce code , je reçois une assertion a échoué, car la taille Vector_2d ne correspond pas à la taille 3D:

Eigen::Vector3d testVector3d = myFunc<3>(); // failed, because 3d doesn't fit the theoreticelly possible 2d 

en fait, l'affirmation a échoué est compréhensible, mais bien sûr, ce ne sera jamais un problème lors de l'exécution. Comment puis-je contourner cette affirmation qui a échoué? Ou y a-t-il un moyen plus élégant que l'état du commutateur?

Merci!

+0

pourquoi ne pas [se spécialiser pleinement] (http://en.cppreference.com/w/cpp/language/template_specialization) le modèle de func? –

Répondre

3

déclare juste la fonction de modèle et ne définissent pas, définissent alors deux spécialisations:

template <int nSize> 
Eigen::Matrix<double, nSize, 1> myFunc(); 

template <> 
Eigen::Matrix<double, 2, 1> myFunc<2>() 
{ 
    return ExternalLibrary::generate_Vector_2d(); 
} 

template <> 
Eigen::Matrix<double, 3, 1> myFunc<3>() 
{ 
    return ExternalLibrary::generate_Vector_3d(); 
} 

Le compilateur, alors qu'il éliminera le code mort comme une optimisation, doit vérifier la validité du code mort de toute façon, ce qui signifie qu'il doit s'assurer que le type de retour de ExternalLibrary::generate_Vector_3d() peut être converti en Eigen::Matrix<double, 2, 1>, même s'il peut être prouvé que cette déclaration de retour ne peut pas être exécutée. Parce que cette conversion n'est pas autorisée, vous obtenez une erreur de compilation.

En séparant les deux déclarations de retour dans des spécialisations différentes, vous éliminez ce problème, car il élimine la déclaration return ExternalLibrary::generate_Vector_3d(); d'une fonction qui pourrait retour autre chose qu'un Eigen::Matrix<double, 3, 1>.


Notez que l'utilisation myFunc() avec un autre nSize que 2 ou 3 provoquera une erreur de lien. Nous pouvons passer cette erreur de compilation en fournissant un corps qui ne parviendra pas à instancier, mais (apparemment) dépend de nSize afin que le compilateur ne tentera pas de instancier avant qu'il ne soit utilisé:

template <int nSize> 
Eigen::Matrix<double, nSize, 1> myFunc() 
{ 
    // With C++11, the following line provides a more useful diagnostic. If 
    // you don't have C++11 support, remove it and the bad return statement 
    // will do the job, albeit with a more cryptic error message. 
    static_assert((static_cast<void>(nSize), false), "Invalid template parameter nSize"); 

    return static_cast<class INVALID_NSIZE_PARAMETER**********>(nSize); 
} 

Cela fournira un diagnostic indiquant l'utilisation incorrecte de myFunc(). Par exemple, sans support 11 C++ vous verriez quelque chose comme:

main.cpp:12:12: error: cannot cast from type 'int' to pointer type 'class INVALID_NSIZE_PARAMETER **********' 
    return static_cast<class INVALID_NSIZE_PARAMETER**********>(nSize); 
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
main.cpp:29:5: note: in instantiation of function template specialization 'myFunc<4>' requested here 
    myFunc<4>(); 
    ^
+0

C'est une réponse parfaite, merci! Mon code fonctionne déjà. – macmallow