C++ 为什么我的变体将std::string转换为bool?

C++ 为什么我的变体将std::string转换为bool?,c++,c++17,variant,C++,C++17,Variant,我的std::variant可以为空(std::monostate),包含int、std::string或bool 当我想给它输入一个字符串时(给定为var=“this is my string”),它会被转换为bool,而不是字符串。如果我显式声明该类型,它将工作var=std::string(“这是我的字符串”)。为什么会这样?我能做些什么来避免它吗 #include <string> #include <variant> #include <iostream&

我的
std::variant
可以为空(
std::monostate
),包含
int
std::string
bool

当我想给它输入一个字符串时(给定为
var=“this is my string”
),它会被转换为
bool
,而不是字符串。如果我显式声明该类型,它将工作
var=std::string(“这是我的字符串”)
。为什么会这样?我能做些什么来避免它吗

#include <string>
#include <variant>
#include <iostream>

int main()
{
    using var = std::variant<std::monostate, int, std::string, bool>;

    var contains_nothing;    
    var contains_int = 5;
    var contains_string = "hello";
    var contains_expl_string = std::string("explicit hello");
    var contains_bool = false;

    auto visitor = [](auto&& arg){
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same<T, std::monostate>())
                std::cout<<"nothing\n";
            else if constexpr (std::is_same<T, int>())  
                std::cout<<"int: "<<arg<<"\n";
            else if constexpr (std::is_same<T, std::string>())  
                std::cout<<"string: "<<arg<<"\n";
            else if constexpr (std::is_same<T, bool>())  
                std::cout<<"bool: "<<arg<<"\n";
            else 
                std::cout<<"Visitor is not exhaustive\n";
        };

    std::visit(visitor, contains_nothing);       // nothing
    std::visit(visitor, contains_int);           // int: 5
    std::visit(visitor, contains_string);        // bool: 1
    std::visit(visitor, contains_expl_string);   // string: explicit hello
    std::visit(visitor, contains_bool);          // bool: 0    
}
“hello”
不是
std::string
,它是
const char*
,可以隐式转换为bool,也可以用来构造
std::string

换句话说,这很好:

int main() {
    bool b = "foo";
    (void)b;
}
如@aschepler的评论所述:

const char*
bool
的隐式转换优于从
const char*
std::string
的用户定义转换
int
根本不是一个选项

“hello”
的类型是
常量字符[6]
,它会衰减为
常量字符*
。从
const char*
bool
的转换是内置转换,而从
const char*
std::string
的转换是用户定义的转换,这意味着执行前者

由于使用C++ +>=14,可以使用后缀<代码>代码> >代码来表示<代码> STD::String :

using namespace std::string_literals;

var contains_string = "hello"s;

另一个问题是,为什么
std::string
bool
更受欢迎?两者都需要数组衰减和类型转换。请参阅我的可爱答案,特别是我使用模板的变通方法;-)。但Angew使用用户定义的文字(见下文)更可爱。简短回答:不是,因为这不是你给它的
std::string
。这里没有UB。从
const char*
bool
的隐式转换优于从
const char*
std::string
的用户定义转换<代码> int 根本不是一个选项。@ AsChisher谢谢,固定了。为什么它没有拿起<代码> int >代码>类型而不是<代码> BoOL ?@ SkPyJokes,因为C++中没有隐含的指针指向代码> int < /Cord>转换。确实有意义。谢谢。:-)是否有一种可能的修复方法可以防止从
const char*
转换为
string
,而无需显式?
using namespace std::string_literals;

var contains_string = "hello"s;