Собственно заголовок говорит сам за себя =) В очередной раз получил ТЛ из-за сина. Что в этом случае делает нормальный человек? Переходит наконец на сканф/принтф. Что делаю я? Пишу какую-то ересь, которая подменяет одно другим.
#ifdef WIN32
#define LLD "%I64d"
#else
#define LLD "%l" "ld"
#endif
#define cin mycin
#define cout mycout
#define endl '\n'
struct io {
io operator» (int& x) {scanf("%d",&x); return *this; }
io operator» (LL& x) {scanf(LLD,&x); return *this; }
io operator» (double& x) {scanf("%lf",&x); return *this; }
io operator» (char& x) {scanf("%c",&x); return *this; }
io operator» (char* x) {scanf("%s",x); return *this; }
io operator» (string& x) {scanf("%s",x.c_str()); return *this; }
io operator« (int x) {printf("%d",x); return *this; }
io operator« (LL x) {printf(LLD,x); return *this; }
io operator« (double x) {printf("%.8lf",x); return *this; }
io operator« (char x) {printf("%c",x); return *this; }
io operator« (char* x) {printf("%s",x); return *this; }
io operator« (string x) {printf("%s",x.c_str()); return *this; }
};
io cin, cout;
Вряд ли этот адовый ад стоит использовать в жизни. Но чисто теоретически интересно: будет ли это работать достаточно быстро? Или такая структура существенно утяжеляет "голые" сканф/принтф? И, возможно, стоит как-то пошаманить с typeof и сделать несколько кейсов внутри одной перегрузки, чем писать 100500 их? В общем, интересно, насколько оптимальным это может быть.
7647752
Спасибо, уже знаю =) Просто вот тут (если я правильно понимаю статистику-результат) говорится о том, что под студией cin/cout даже с этими оптимизациями работает медленнее. Мне интересно, насколько плох именно этот изврат.
По идее, вызов функции — операция в десятки раз более дешевая, нежели непосредственно ввод-вывод.
Тем более, функции-члены у Вас тут невиртуальные, вызов таких функций отличается от вызова обычных только необходимостью передавать в качестве еще одного параметра указатель на объект.
Но, ИМХО, писать такой код — извращение. Даже в олимпиадном контексте. Тем более, что выше уже привели более простой вариант (правда, работающий только под GCC).
Возвращать надо io&. И в io::operator<< передавать string const&.
Нисколько не утяжелит. Лишний вызов функции — чепуха, по сравнению с тем, что происходит внутри сканфа. К тому же можно заинлайнить.
Перегрузка никоим образом не влияет на время выполнения, так как то, какая функция будет вызываться, известно уже на стадии компиляции.
Функция считывания стрингов написана неправильно. Код же даже не компилируется:
c_str()
этоconst char*
, его содержимое менять нельзя.Стандартом 2003 года языка C++ не регламентируется, что
basic_string<T>
должен быть реализован как сплошной массив символов. Условно говоря, стринг может быть двусвязным списком символов. Поэтомуc_str()
вполне может быть реализован как "копируем содержимое строки в некоторый буфер и возвращаем этот новосозданный буфер". Стало быть, считывание в него, не приведёт к изменению самой строки. Впрочем, вроде, ни один разумный компилятор так не делает. А вот в стандарте 2011 года в пункте 21.4.1.5 уже регламентировано, что строка реализуется как сплошной массив символов поэтому можно писатьscanf("%s", &(*x.begin()))
.С другой стороны, у этого подхода есть проблема, заключающаяся в том, что приходится аккуратно контролировать вместимость строки: считывание может запросто переполнить зарезервированный буфер. Также после считывания
x.size()
не будет иметь никакого отношения к реальной хранимой строки,scanf
плюхнет где-то внутри нулевой символ, и это никак не отразится на том, что про длину строки думает структура.Странно, у меня спокойно компилируется (VS C++ 2005 Express). А со стрингами действительно лажа, спасибо, сначала не заметил, хотя проверял вроде.
Действительно, это дело компилируется, но с warning'ом, а у меня стоит опция treat warnings as errors. В общем, не стоит так делать.