Interpréter une valeur d'un boost::any
Bonjour,
Je suis dans une situation où j'appelle une fonction virtuelle dont le resultat peut être d'un type different selon le contexte. J'ai donc déclaré la fonction en mettant boost::any en type de retour. Le problème est que j'ai du mal à restaurer le boost::any dans le type désiré initialement.
Voici en gros mon contexte.
Code:
1 2 3 4 5 6 7 8 9 10 11
| class context
{
public:
template<typename T>
T convert( const std::string& s ) const
{
return converter<T>::convert(*this, s);
}
virtual boost::any custom_convert( const std::string& s ) const = 0;
}; |
Je demande la conversion d'une chaîne dans un type connu en appelant context::convert<LeType>(s). Selon que je sache faire la conversion moi-même ou pas, une implémentation de la classe converter ci-dessous est choisie (c'est simplifié) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| // traite le cas général
template<typename T>
struct converter
{
T convert( const context& c, const std::string& s ) const;
};
// traite le cas particulier d'une référence à un objet quelconque.
template<typename T>
struct converter<const T&>
{
const T& convert( const context& c, const std::string& s ) const
{
// on demande à la classe fille de se charger de la conversion
const boost::any result = c.custom_convert(s);
// échoue si c.custom_convert a retourné un T* au lieu d'un const T*
return *boost::any_cast<T>( &result );
}
}; |
Le problème est au niveau du return ci dessus. Si le type de la valeur retournée par c.custom_convert(s) n'est pas exactement const T*, alors la conversion échoue. Même si c'est un T*. Ce n'est pas surprenant quand on regarde le code de boost::any, mais je cherche une solution de remplacement.
J'ai essayé plusieurs pistes*:
- remplacer le boost::any_cast<T> par boost::unsafe_any_cast<T>() ;
- faire une sorte de boost::any maison, en gardant l'idée du placeholder/holder<T> et en ajoutant un cast utilisant un dynamic_cast ;
- passer par un void* dans un boost::any maison et utiliser un reinterpret_cast
Aucune n'a été satisfaisante. Soit j'ai un problème avec la présence ou non d'un const dans le type de retour de custom_convert(), soit c'est que le custom_convert me retourne un pointeur sur une classe mère du type attendu, qui pourrait bien se convertir avec un dynamic_cast mais qui ne passe pas avec le holder<T> et ne se reinterpret_cast pas correctement depuis un void*.
La dernière piste que j'ai est de passer le type_info du résultat attendu en paramètre à custom_convert, et imposer à la classe fille de me retourner un résultat ayant exactement le même type_info ou d'échouer. Ça ne me plaît pas beaucoup alors j'aimerais avoir vos avis sur le sujet avant de me lancer.