问题
I was working with boost::variant<int,std::string,bool>
and its visitors when I runned into an unexpected behavior: the string and bool values were comparable. I don't know, why does it work like this, but I found it interesting. My only idea is that the variant with the bool value was interpreted as a char? Someone could explain it to me?
The comparsion visitor:
#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 Here is an extended main function with some test cases:
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);
}
The output:
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:
OK, now that you've completely changed your program, let me try again.
The problem is:
datatype *b = new datatype("abc");
"abc"
is a const char*
, not a std::string
. If you want to create a std::string
variant, you need to do so explicitly. Otherwise, you'll end up creating a bool
variant because all pointers are convertible to bool
, including const char*
pointers.
Try this
datatype *b = new datatype(std::string("abc"));
This interaction between bool
and std::string
is apparently well-known and somewhat irritating. boost::variant
provides a templated constructor, but the resolution rules prefer the built-in converstion to bool
and there's no way in C++ to specify a template specialization on a constructor. It is possible to explicitly specialize assignment, so you can write:
datatype b;
b.operator=<std::string>("abc");
which might be marginally more efficient but much less readable than
datatype b;
b = std::string("abc");
If you don't include bool
as a variant, then string literals do automatically convert to std::string
. Maybe it's possible to use some sort of proxy pseudo-boolean class. I've never tried.
来源:https://stackoverflow.com/questions/14371760/string-bool-comparsion-why