singalen: (2002)
[personal profile] singalen
Подарки от Вовы Мутеля - этот и следующий пост. Отсюда.
Задача - дана программа:
#include <iostream>
#include <sstream>
using namespace std;

#define SFORMAT(e) ((dynamic_cast<const ostringstream&>(ostringstream() << e)).str())

int main(int argc, char* argv[])
{
        cout << SFORMAT("2 x " << " 2 = " << 2*2);
        return 0;
}
Никто не спрашивает, что распечатается в результате. Если вы можете это сказать, то вы не Страуструп - вы Господь Бог.
Вопрос: почему первый const char* распечатывается как указатель, а не так, как надо?
Я пока не смог.
Вове ответил некий истинный гуру из Apple.

(no subject)

2/2/06 07:41 (UTC)
Posted by [identity profile] dottedmag.livejournal.com
Упростим до

ofstream("foobar") << "test";


Заметим, что

ofstream f("foobar");
f << "test";


работает замечательно. Значит временная перменная чем-то отличается от обычной с точки зрения выбора перегрузок.

Проверим, нет ли здесь какой магии:

#include 
using namespace std;

namespace F
{

struct C
{
    C& operator<<(const void*)
    {
        cout << "*";
    }
};

C& operator<<(C&, const char*)
{
    cout << "C";
}

}

using namespace F;

int main()
{
    C() << "test";
    C c;
    c << "test";
}


Даёт нам *C, то есть магии нет, а есть разрешение перегрузок. Дальше пока не продвинулся.

(no subject)

2/2/06 07:59 (UTC)
Posted by [identity profile] dottedmag.livejournal.com
Всё, понял. Удалим внутреннюю функцию и получим ошибку компиляции: C() << "test" не сможет связаться со второй перегрузкой. Почему? Потому что связывание rvalue C() с non-const C& требует создания временного объекта и поэтому первая перегрузка выигрывает.

(no subject)

2/2/06 08:03 (UTC)
Posted by [identity profile] dottedmag.livejournal.com
Точнее, согласно пункту стандарта 8.5.3.5, запрещается создание неконстантных ссылок с инициализацией их rvalue.

Re: Reply to your comment...

2/2/06 08:54 (UTC)
Posted by [identity profile] dottedmag.livejournal.com
Аргумент оператора вне класса - C& - некостантная ссылка, так что
привязать к ней rvalue C() нельзя. Раз так, то эта функция не
выбирается в качестве варианта для перегрузки.

(no subject)

2/2/06 07:47 (UTC)
Posted by [identity profile] http://users.livejournal.com/_gert/
Слух, а чем ты компилил? А то у нас на час работа стала, все понять пытаемся, а скомпилить не удается. :(

(no subject)

2/2/06 07:50 (UTC)
Posted by [identity profile] http://users.livejournal.com/_gert/
Ладно, под вижуалом даже запустили, но unhandled exception :(

(no subject)

2/2/06 08:00 (UTC)
Posted by [identity profile] dottedmag.livejournal.com
Читай выше, я разобрался.

(no subject)

2/2/06 08:25 (UTC)
Posted by [identity profile] fxfuzzy.livejournal.com
в результате дебага выяснилось следующее:
первый параметр выводится в

_Myt& std::basic_ostream::operator<<(const void *_Val).

второй - уже в

template inline
basic_ostream
[Error: Irreparable invalid markup ('<char,>') in entry. Owner must fix manually. Raw contents below.]

в результате дебага выяснилось следующее:
первый параметр выводится в

_Myt& std::basic_ostream::operator<<(const void *_Val).

второй - уже в

template<class _Traits> inline
basic_ostream<char, _Traits>& __cdecl std::operator<<(
basic_ostream<char, _Traits>& _Ostr,
const char *_Val)

почему-то неправильно(?) разрешается перегрузка.