Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;自动类型转换为std::string和char之间的区别* 作为一个学习练习,我一直在研究C++中如何自动转换类型。我知道应该避免自动类型转换,但是我想通过理解它是如何工作的方式来增加我的C++知识。_C++_Type Conversion_Cstring_Stdstring - Fatal编程技术网

C++;自动类型转换为std::string和char之间的区别* 作为一个学习练习,我一直在研究C++中如何自动转换类型。我知道应该避免自动类型转换,但是我想通过理解它是如何工作的方式来增加我的C++知识。

C++;自动类型转换为std::string和char之间的区别* 作为一个学习练习,我一直在研究C++中如何自动转换类型。我知道应该避免自动类型转换,但是我想通过理解它是如何工作的方式来增加我的C++知识。,c++,type-conversion,cstring,stdstring,C++,Type Conversion,Cstring,Stdstring,我创建了一个StdStringConverter类,该类可以自动转换为std::string,但是当对象与真实的std::string进行比较时,编译器(Debian上的g++4.3.4)似乎没有进行转换(请忽略缺少按引用传递和不必要的临时对象创建): 在这个上下文中,std::string和char*之间的区别是否有什么特殊之处,使得编译器不能对它们一视同仁?有多个因素。如果您这样更改return语句 返回(std::operator==(name,name))?0:1 它进行编译,尽管它显然

我创建了一个
StdStringConverter
类,该类可以自动转换为
std::string
,但是当对象与真实的
std::string
进行比较时,编译器(Debian上的g++4.3.4)似乎没有进行转换(请忽略缺少按引用传递和不必要的临时对象创建):


在这个上下文中,
std::string
char*
之间的区别是否有什么特殊之处,使得编译器不能对它们一视同仁?

有多个因素。如果您这样更改return语句

返回(std::operator==(name,name))?0:1

它进行编译,尽管它显然做的不是同一件事

返回(std::operator==(转换器,名称))?0:1

但提供了一条更有趣的错误消息

对“operator==”的调用没有匹配的函数(StdStringConverter&,const std::string&)

这提醒我操作符==是以基本的_字符串为模板的,它有三个模板参数要引导。如果在示例中使用int而不是std::string,编译器不会抱怨


如何使用std::string获得所需的效果更有趣…

在第一个示例中,比较了两个类(string和StdStringConverter)对于类型转换,请不要从编译器处获得任何特殊处理。这意味着您所做的运算符重载甚至不会被触发。编译器会查看运算符==重载的列表,其中没有一个会接收StdStringConverter,因此它会对您大喊大叫

在第二个示例中,名称是char*。因为它是一种基本类型,所以编译器尝试将非基本类型转换为char*。因为您有一个覆盖,它可以工作,并且您可以比较地址

编译器不会对不包含基元类型的操作执行显式类型转换。它将尝试使用构造函数使类型匹配。例如,如果将第一个示例更改为:

#include <string>

class StdStringConverter
{
public:
    StdStringConverter(std::string name) : m_name(name) {}
    bool operator==(const StdStringConverter &name) { return m_name == name.m_name; }
    operator const std::string () const { return m_name; }
private:
    std::string m_name;
};

int main()
{
    StdStringConverter converter(std::string("Me"));
    const std::string name = "Me";
    // Next line causes compiler error:
    // no match for 'operator==' in 'converter == name'
    return (converter == name) ? 0 : 1;
}
#包括
类StdStringConverter
{
公众:
StdStringConverter(std::string name):m_name(name){}
bool运算符==(const StdStringConverter&name){return m_name==name.m_name;}
运算符const std::string()const{return m_name;}
私人:
std::字符串m_名称;
};
int main()
{
StdStringConverter转换器(std::string(“Me”);
const std::string name=“Me”;
//下一行导致编译器错误:
//“converter==name”中的“operator==”不匹配
返回值(converter==name)?0:1;
}

现在程序返回0。由于构造函数现在不是显式的,编译器将尝试使用它将字符串转换为StdStringConverter。由于StdStringConverter中现在有一个运算符==一切正常。

问题在于std::string实际上是类模板std::basic_string的实例。a名称空间std中可用的n运算符==采用两个std::basic_字符串模板:


template<class charT, class traits, class Allocator>
bool operator==(const basic_string& lhs,
                const basic_string& rhs);

模板
布尔运算符==(常量基本字符串和lhs,
常量基本字符串和rhs);
如果此版本的运算符==是专门在std::string上重载的,那么您的代码就可以了。但事实并非如此,这需要编译器对std::basic_string的模板参数执行模板参数推断,以便理解转换运算符的返回可能是匹配的

但是,编译器不会这样做。我不知道标准的哪一部分精确地说明了这一点。但是一般的想法是,这种转换只适用于非模板类型

我建议您将StdStringConverter放在一个名称空间中,并在该名称空间中为std::string提供一个operator==的版本。这样,当您的编译器找到一个类似ADL(参数相关查找)的表达式时,一切正常


#include <string>

namespace n1 {

class StdStringConverter
{
public:
    explicit StdStringConverter(std::string name) : m_name(name) {}
    operator std::string () { return m_name; }
private:
    std::string m_name;
};

bool operator==(std::string const& a, std::string const& b)
{
  return a == b; //EDIT: See Paul's comment on std::operator== here.
}

}

int main()
{
    using namespace n1;
    StdStringConverter converter(std::string("Me"));
    std::string name = "Me";
    return (converter == name) ? 0 : 1;   
}

#包括
名称空间n1{
类StdStringConverter
{
公众:
显式StdStringConverter(std::string name):m_name(name){}
运算符std::string(){return m_name;}
私人:
std::字符串m_名称;
};
布尔运算符==(标准::字符串常量&a,标准::字符串常量&b)
{
返回a==b;//编辑:请参见Paul对std::operator==的评论。
}
}
int main()
{
使用名称空间n1;
StdStringConverter转换器(std::string(“Me”);
std::string name=“Me”;
返回值(converter==name)?0:1;
}

请参见接受答案,该注释是字符串的有用信息,但不涉及比较问题+1,当然,这正是发生的情况。标准中的段落是
14.8.2.1
,其中列出了参数推断期间可能的转换。不允许用户定义转换以使推断成功d、 当然。
14.8.1/4
最后允许所有隐式转换在参数不包含要推导的模板参数(不再)的情况下进行。
14.8.3/1
上的脚注包含进一步的解释(请注意,这只是信息性的,不是规范性的):推导参数上允许的转换集是有限的,因为参数推导过程生成的函数模板的参数要么与调用参数完全匹配,要么仅在允许的有限转换可以桥接的方式上不同。非推导参数允许整个转换范围。“@litb-谢谢你的参考:)谢谢你的解释。但是,当我尝试您的代码时,我得到一个segfault:调试器说“a==b”正在递归地调用自己。将其更改为“return std::operator==(a,

template<class charT, class traits, class Allocator>
bool operator==(const basic_string& lhs,
                const basic_string& rhs);

#include <string>

namespace n1 {

class StdStringConverter
{
public:
    explicit StdStringConverter(std::string name) : m_name(name) {}
    operator std::string () { return m_name; }
private:
    std::string m_name;
};

bool operator==(std::string const& a, std::string const& b)
{
  return a == b; //EDIT: See Paul's comment on std::operator== here.
}

}

int main()
{
    using namespace n1;
    StdStringConverter converter(std::string("Me"));
    std::string name = "Me";
    return (converter == name) ? 0 : 1;   
}