ZS>Есть простенький код:
Я вообще не понимаю, как твой "простенький код" компилируется. У basic_streembuf (специализацией которого является ostringstream) конструктор копирования private, и копировать его нельзя.
Здравствуйте, ZegSoft, Вы писали:
ZS>Здравствуйте. ZS>Есть простенький код:
ZS>Объясните пожалуйста, почему на выходе получается ZS>
ZS>-1 ZS>5 ZS>5.5 ZS>116 ZS>00417890 ZS>ZS>То есть, строки и символы выводятся некорректно. В чем причина и как это можно исправить?
Причина в том, что для строк и символов используется operator<< определённый как свободная функция, а для других тnипов — методы ostringstream. Свободные функции имеют сигнатуры вида
ostringstream & operator<<(ostringstream & stream, type value), поэтому они не могут использоваться для временных объектов, в результате вызываются методы для целых и указателей. Исправить можно, например, определив для MyStream соответствующие методы:
class MyStream
{
// ...public:
using ostringstream::operator<<; // нужно, чтобы операторы MyStream не скрывали операторы ostringstream
MyStream & operator<<(char const * value)
{
std::operator<<(*this, value);
return *this;
}
//...
};
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, ZegSoft, Вы писали:
ZS>>Здравствуйте. ZS>>Есть простенький код:
ZS>>Объясните пожалуйста, почему на выходе получается ZS>>
ZS>>-1 ZS>>5 ZS>>5.5 ZS>>116 ZS>>00417890 ZS>>ZS>>То есть, строки и символы выводятся некорректно. В чем причина и как это можно исправить?
KO>Причина в том, что для строк и символов используется operator<< определённый как свободная функция, а для других тnипов — методы ostringstream. Свободные функции имеют сигнатуры вида KO>ostringstream & operator<<(ostringstream & stream, type value), поэтому они не могут использоваться для временных объектов, в результате вызываются методы для целых и указателей. Исправить можно, например, определив для MyStream соответствующие методы: KO>
Сегодня обнаружил удивительную особенность. Попробовал скомпилировать в VS2010 и вуаля: все работает как надо!!! А при компиляции в VS2008 вместо строк появляются цифры, как указано в примере. Почему такое различное поведение?
Re[2]: Наследование от ostringstream. В чем ошибка?
Здравствуйте, Vamp, Вы писали:
ZS>>Есть простенький код: V>Я вообще не понимаю, как твой "простенький код" компилируется. У basic_streembuf (специализацией которого является ostringstream) конструктор копирования private, и копировать его нельзя.
А это вопрос уже к нашему любимому дядюшке биллу)) Во всех студиях компилится даже без предупреждений)
Re[2]: Наследование от ostringstream. В чем ошибка?
Здравствуйте, andrey.desman, Вы писали:
AD>Здравствуйте, ZegSoft, Вы писали:
ZS>>То есть, строки и символы выводятся некорректно. В чем причина и как это можно исправить?
AD>Использую такую конструкцию (предложил ее не так давно по-моему remark) AD>
AD>Допилить ее до нужного тебе поведения не проблема.
Первоначально я так и сделал. Но указанный пример не позволяет использовать функторы STL. То есть, например, если я напишу
sfmt()<<"Test"<<std::endl;
Компилятор будет ругаться.
Можно конечно переделать operator <<, чтобы он возвращал не sfmt&, а ostringstream&. В этом случае, указанный пример будет работать. Однако если поменять местами строку и endl
sfmt()<<std::endl<<"Test";
появятся все те же ошибки компиляции.
Следовательно, такой подход тоже не подходит, так как иногда бывает нужно настроить параметры форматирования через функторы STL (например точность вывода чисел с плавабщей запятой).
Кстати попробовал скомпилировать свой первоначальный пример в VS2010 — все работает как надо. А в VS2008 — вместо строк выводятся цифры. Почему такая разница??
Здравствуйте, ZegSoft, Вы писали:
ZS>То есть, строки и символы выводятся некорректно. В чем причина и как это можно исправить?
MyStream Prot()
{
return MyStream();
}
Очевидно тут компилятор применил RVO и этот код соптимизировался.
Т.е. из
Prot()<<-1;
Мы получили
MyStream()<<-1;
Далее происходит следующее:
Для чисел вызывается встроенный метод.
Для строк имеется отдельная функция которая принимает stream&.
Ввиду того что у нас временный объект stringstream (MyStream) компилятор не может выбрать эту функцию.
Однако имеется встроенный метод , принимающий void*, вот его компилятор и выбирает. Что мы и видим.
Резюмирая это все, в VC есть баг.
Невзирая на невозможность создания конструктора копирования мы имеем возможность "копировать" объект.
Кстати, при /Wall можно получить предупреждение о том, что невозможно сгенерировать конструктор копирования.
Здравствуйте, ZegSoft, Вы писали:
ZS>Здравствуйте, k.o., Вы писали:
KO>>Здравствуйте, ZegSoft, Вы писали:
ZS>>>Здравствуйте. ZS>>>Есть простенький код:
ZS>Сегодня обнаружил удивительную особенность. Попробовал скомпилировать в VS2010 и вуаля: все работает как надо!!! А при компиляции в VS2008 вместо строк появляются цифры, как указано в примере. Почему такое различное поведение?
r-value references в VS2010 добавились перегрузки операторов << принимающие r-value reference на stream, что позволяет использовать их с временными объектами, поэтому там выбираются правильные операторы для символов и строк.
Re[4]: Наследование от ostringstream. В чем ошибка?
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, ZegSoft, Вы писали:
ZS>>Здравствуйте, k.o., Вы писали:
KO>>>Здравствуйте, ZegSoft, Вы писали:
ZS>>>>Здравствуйте. ZS>>>>Есть простенький код:
ZS>>Сегодня обнаружил удивительную особенность. Попробовал скомпилировать в VS2010 и вуаля: все работает как надо!!! А при компиляции в VS2008 вместо строк появляются цифры, как указано в примере. Почему такое различное поведение?
KO>r-value references в VS2010 добавились перегрузки операторов << принимающие r-value reference на stream, что позволяет использовать их с временными объектами, поэтому там выбираются правильные операторы для символов и строк.
Ясно) Спасибо за разъяснения.
Объединив советы получился такой код (в Ващем примере не был перегружен оператор для char, соответственно отдельные символы выводились цифрами. чтобы не копировать код, решил сделать оператор шаблонным).
class MyStream:public ostringstream
{
public:
MyStream(){}
~MyStream()
{
cout<<str().c_str()<<endl;
}
using ostringstream::operator<<; // нужно, чтобы операторы MyStream не скрывали операторы ostringstreamtemplate<typename T>
MyStream & operator<<(T value)
{
std::operator<<(*this, value);
return *this;
}
};
Кстати, тут многие пишут, что этот код не валидный и компилится исключительно из-за багов в MSVS. Каково Ваше мнение по этому поводу?
Re[5]: Наследование от ostringstream. В чем ошибка?
Здравствуйте, ZegSoft, Вы писали:
ZS>Кстати, тут многие пишут, что этот код не валидный и компилится исключительно из-за багов в MSVS. Каково Ваше мнение по этому поводу?
Полностью с ними согласен.
Re[3]: Наследование от ostringstream. В чем ошибка?
Здравствуйте, ZegSoft, Вы писали:
ZS>Здравствуйте, Vamp, Вы писали:
ZS>>>Есть простенький код: V>>Я вообще не понимаю, как твой "простенький код" компилируется. У basic_streembuf (специализацией которого является ostringstream) конструктор копирования private, и копировать его нельзя. ZS>А это вопрос уже к нашему любимому дядюшке биллу)) Во всех студиях компилится даже без предупреждений)
use codepad, Luke!
Re[5]: Наследование от ostringstream. В чем ошибка?