隐式转换为std :: string

Mih*_*dor 13 c++ string operator-overloading

可能重复:
通过隐式转换为字符串来流对象时,重载决策失败

我知道这样做并不是一个好主意,但我真的想知道下面的代码无法编译的原因(即为什么"没有可接受的转换"):

#include <iostream>
#include <string>


class Test
{
public:
    operator std::string () const;
};

Test::operator std::string () const
{
    return std::string("Test!");
}

int main ()
{
    std::string str = "Blah!";
    std::cout << str << std::endl;

    Test test;

    str = test;//implicitly calls operator std::string without complaining

    std::cout << str << std::endl;

    std::cout << test;//refuses to implicitly cast test to std::string

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在Visual Studio 2010上,我收到此错误:" error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Test' (or there is no acceptable conversion)"

为了使用它,<<运算符是否隐式转换std::string为其他内容?如果是的话,我需要在课堂上重载什么操作才能使这样的事情发挥作用?我拒绝相信我真的需要使用operator char *.

Pra*_*ian 13

operator<<(std::basic_ostream&, std::basic_string)是一个函数模板,在模板参数推导期间不考虑用户定义的转换.你需要operator<<为你的课超载.

当然,另一种选择是演员

std::cout << static_cast<std::string>(test);
Run Code Online (Sandbox Code Playgroud)

  • "显性演员"是多余的. (2认同)
  • 实际上,这是因为[在所需的隐式转换中有参与演绎的模板参数](http://stackoverflow.com/a/7505108/560648). (2认同)

Mik*_*our 11

问题是std::string模板的特化std::basic_string<char>,并且所需的重载operator<<本身就是一个模板:

template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>&& os,
               const basic_string<charT,traits,Allocator>& str);
Run Code Online (Sandbox Code Playgroud)

为了用于模板参数推导,用户定义的类型必须是完全匹配; 不考虑转换.

您需要operator<<为您的类提供重载,或者显式转换为std::string.


Che*_*Alf 5

通常,这取决于<<类的流插入运算符是具体函数还是模板。

随着<<作为具体的功能,过载时发现,转换完成的(只要它不是暧昧):

#include <iostream>
using namespace std;

template< class CharType >
struct String {};

ostream& operator<<( ostream& stream, String<char> const& s )
{
    return (stream << "s");
}

struct MyClass
{
    operator String<char> () const { return String<char>(); }
};

int main()
{
    cout << "String: " << String<char>() << endl;
    cout << "MyClass: " << MyClass() << endl;
}
Run Code Online (Sandbox Code Playgroud)

但是,<<作为函数模板,模板匹配找不到匹配项,则不会尝试通过用户定义的运算符进行转换:

#include <iostream>
using namespace std;

template< class CharType >
struct String
{
};

template< class CharType >
ostream& operator<<( ostream& stream, String< CharType > const& s )
{
    return (stream << "s");
}

struct MyClass
{
    operator String<char> () const { return String<char>(); }
};

int main()
{
    cout << "String: " << String<char>() << endl;
    cout << "MyClass: " << MyClass() << endl;       // !Oops, nyet! Not found!
}
Run Code Online (Sandbox Code Playgroud)

在你的情况下,std::string真的只是一个typedeffor std::basic_string<char>

修复:<<为你的类定义一个操作符,或者,如果你想避免头依赖(考虑构建时间),定义一个转换到 eg char const*,或者,最简单的和我推荐的,使该转换成为一个命名的转换,以便它必须是显式调用。

显式好,隐式不好。

  • @MihaiTodor:哦,参数推导尝试将`MyClass`(`&lt;&lt;`调用的实际参数类型)与`std::basic_string&lt;C, T, A&gt;`(形式参数类型)匹配,其中` C`、`T` 和 `A` 是模板参数。但是没有选择这些参数可以将“MyClass”变成完全匹配或任何类型的匹配。对于模板参数匹配仅考虑直接、精确匹配,而不考虑任何用户定义的转换。模板参数匹配支持的唯一“转换”是导出到基数。 (2认同)