Неявное преобразование в std::string
Возможный дубликат:
Сбой разрешения перегрузки при потоковом объекте через неявное преобразование в строку
Я знаю, что это не такая хорошая идея, но я действительно хочу знать причину, почему приведенный ниже код не компилируется (т.е. почему нет "приемлемого преобразования" ):
#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;
}
В 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 *
.
Ответы
Ответ 1
operator<<(std::basic_ostream&, std::basic_string)
- это шаблон функции, и пользовательские преобразования не учитываются при выводе аргумента шаблона. Вам нужно перегрузить operator<<
для вашего класса.
Другим вариантом, конечно же, является литой
std::cout << static_cast<std::string>(test);
Ответ 2
Проблема заключается в том, что 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);
Для использования при выводе аргумента шаблона определяемый пользователем тип должен быть точным совпадением; конверсии не учитываются.
Вам нужно либо предоставить перегрузку operator<<
для вашего класса, либо явно преобразовать в std::string
.
Ответ 3
В общем случае это зависит от того, является ли оператор вставки потока <<
для класса конкретной функцией или шаблоном.
С <<
в качестве конкретной функции найдена перегрузка и выполняется преобразование (если оно не является двусмысленным):
#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;
}
Однако при <<
как шаблоне функции совпадение шаблонов не находит совпадения, а затем не выполняется преобразование через пользовательский оператор:
#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!
}
И в вашем случае std::string
на самом деле просто typedef
для std::basic_string<char>
.
Исправить: определить оператор <<
для вашего класса или, если вы хотите избежать зависимости заголовка (время построения мышью), определить преобразование, например. char const*
, или, что проще и что я рекомендую, сделайте это преобразование именованным так, чтобы он был явно вызван.
Явный хороший, неявный плохо.
Ответ 4
Я думаю, что оператор, который вам нужно переопределить, равен "< <".
Ответ 5
Вам нужно переопределить метод operator<<
.
std::ostream & operator <<(std::ostream & os, const Test & t) {
return os << std::string(t);
}