作为一个学习练习,我一直在寻找自动类型转换用C如何工作++。我的知道的那个类型的自动转换一般应避免,但我想通过了解它是如何工作无论如何增加我的C ++知识。

我已经创建了可以被自动转换为一个StdStringConverterstd::string,但是编译器(克++ 4.3.4在Debian)似乎当对象被针对真实std::string相比不进行转换(请忽略缺乏通过按引用和临时对象的不必要创建):

#include <string>

class StdStringConverter
{
public:
    explicit StdStringConverter(std::string name) : m_name(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;
}

在另一方面,如果我稍微改变它的CStringConverter类,自动转换的的发生,虽然可能比较char指针是不是我想要的结果:

#include <string>

class CStringConverter
{
public:
    explicit CStringConverter(std::string name) : m_name(name) {}
    operator const char* () const { return m_name.c_str(); }
private:
    std::string m_name;
};

int main()
{
    CStringConverter converter(std::string("Me"));
    const char* name = "Me";
    // Next line compiles fine, but they are not equal because the
    // pointers don't match.
    return (converter == name) ? 0 : 1;
}

有什么特殊的地方std::string并在这方面,使编译器没有把他们同一个char*区别?

有帮助吗?

解决方案

的问题是由于这样的事实的std :: string实际上是类模板的std :: basic_string的的一个实例。操作者==即在空间std可用采用两个标准:: basic_string的模板:


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

如果这个版本的==操作符的是对的std :: string具体超载,你的代码就可以了。但是,这并非如此,这就需要编译器上性病的模板参数进行模板参数推导:: basic_string的,因此它可以了解您的转换运营商的收益是可能的搭配。

然而,编译器将不这样做。我不知道这恰恰是标准规定的哪一部分。但总的想法是,这样的转换对于非模板类型才能正常工作。

有一件事我可以建议是你把StdStringConverter在一个命名空间,并提供了性病该命名空间下一个版本的==操作符的:: string的。这样,当你的编译器发现这样的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;   
}

其他提示

在第一个例子中的两个被比较的类(字符串和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程序返回0。由于现在有在StdStringConverter一切正常操作==。

有多种因素。如果你改变了return语句正是如此

返回(标准::运算符==(姓名,名))? 0:1;

汇编,虽然它显然不会做同样的事情。在另一方面

返回(标准::运算符==(转换器,名))? 0:1;

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

有呼叫到“运算符==没有匹配的功能(StdStringConverter&,常量的std :: string&)

这让我想起那个==操作符是模板上的basic_string <>,里面有三个模板参数启动。如果你在你的例子使用int而不是的std :: string,编译器不抱怨。

如何获得具有的std :: string期望的效果是更有趣...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top