2013-01-17 1 views
2

Je travaillais avec boost::variant<int,std::string,bool> et ses visiteurs lorsque j'ai eu un comportement inattendu: les valeurs de string et de bool étaient comparables. Je ne sais pas, pourquoi ça marche comme ça, mais je l'ai trouvé intéressant. Ma seule idée est que la variante avec la valeur bool a été interprétée comme un char? Quelqu'un pourrait me l'expliquer? Le visiteur comparsion:Comparsion String-bool - pourquoi?

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <boost/variant.hpp> 
#include <boost/function.hpp> 

struct my_less : boost::static_visitor<bool*> 
{ 
    template<typename T> 
    bool* operator()(T a, T b) const 
    { 
     return a<b ? new bool(true) : new bool(false); 
    } 

    template<typename T, typename U> 
    bool* operator()(T a, U b) const 
    { 
     return NULL; 
    } 
}; 

int main() 
{ 
typedef boost::variant<int,bool,std::string> datatype; 
datatype *a = new datatype(false); 
datatype *b = new datatype("abc"); 

my_less cmp; 

bool* val = boost::apply_visitor(cmp,*a,*b); 

if(val) 
{ 
    std::cout << *val; 
} 
else 
{ 
    std::cout << "NULL"; 
} 

} 

EDIT Voici une fonction principale étendue avec des cas de test:

void show_result(bool* val) 
{ 
if(val) 
{ 
    std::cout << *val << std::endl; 
} 
else 
{ 
    std::cout << "NULL" << std::endl; 
} 
} 

int main() 
{ 
//std::string a = "bbb"; 
//bool b = true; 
//std::cout << b<a;  //compilation error 

typedef boost::variant<int,bool,std::string> datatype; 
datatype int_value_1(4); 
datatype int_value_2(3); 
datatype string_value("abc"); 
datatype bool_value(true); 
my_less cmp; 

std::cout<<"First result, compare ints 4 and 3:"<<std::endl; 
bool* val = boost::apply_visitor(cmp,int_value_1,int_value_2); 
show_result(val); 

std::cout<<"Second result, compare int to string 4 to abc " << std::endl; 
val = boost::apply_visitor(cmp,int_value_1,string_value); 
show_result(val); 

std::cout <<"Third result, int 4 to bool true:" << std::endl; 
val = boost::apply_visitor(cmp,int_value_1,bool_value); 
show_result(val); 

std::cout<<"Fourth result, string abc to bool true" << std::endl; 
val = boost::apply_visitor(cmp,string_value,bool_value); 
show_result(val); 

} 

La sortie:

First result, compare ints 4 and 3: 
0 
Second result, compare int to string 4 to abc 
NULL 
Third result, int 4 to bool true: 
NULL 
Fourth result, string abc to bool true 
0 
+1

Testcase s'il vous plaît. c'est-à-dire show 'main' –

+0

Comment sont définis 'TRUE' et' FALSE'? – Mankarse

+0

Avant la struct ... Je télécharge le test finalcase, un programme complet. – Zozzzzz

Répondre

4

OK, maintenant que vous avez complètement changé votre programme, laissez-moi essayer à nouveau.

Le problème est:

datatype *b = new datatype("abc"); 

"abc" est un const char*, pas std::string. Si vous voulez créer une variante std::string, vous devez le faire explicitement. Sinon, vous finirez par créer une variante bool car tous les pointeurs sont convertibles en bool, y compris les pointeurs const char*.

Essayez cette

datatype *b = new datatype(std::string("abc")); 

Cette interaction entre bool et std::string est apparemment bien connu et un peu irritant. boost::variant fournit un constructeur basé sur un modèle, mais les règles de résolution préfèrent la conversion intégrée à bool et il n'existe aucun moyen en C++ pour spécifier une spécialisation de modèle sur un constructeur. Il est possible de se spécialiser explicitement l'affectation, de sorte que vous pouvez écrire:

datatype b; 
b.operator=<std::string>("abc"); 

qui pourrait être légèrement plus efficace mais beaucoup moins lisible que

datatype b; 
b = std::string("abc"); 

Si vous n'incluez pas bool comme variante, puis les littéraux de chaîne convertissent automatiquement en std::string. Peut-être qu'il est possible d'utiliser une sorte de classe pseudo-booléenne proxy. Je n'ai jamais essayé.

+0

Désolé de changer le programme, Il fait partie d'un projet plus important, j'ai donc fait quelques échecs lorsque je l'ai copié ici. – Zozzzzz

+0

Avec std :: string cela fonctionne parfaitement, merci! – Zozzzzz

+1

+1 pour "maintenant que vous avez complètement changé votre programme", pour avoir posté une nouvelle réponse, et pour avoir raison. –