Напишите простую функцию, которая работает как & quot; std :: cout & quot; но добавляет разрыв строки в конце

В C ++ есть стандартная библиотечная функция, которая называется cout, что позволяет мне отправлять текст в консоль. Я уверен, что вы это знаете.

#include <iostream>
using std::cout;
cout << "Some Text " << 15 << " Other Text";

Чтобы сделать перевод строки в конце, мне нужно использовать endl,

cout << "Some Text " << 15 << " Other Text" << endl;

Как я могу написать функцию с именем coutl который ведет себя как cout но также добавляет подобный разрыв? Я хочу использовать тот же синтаксис, что cout использует, особенно << оператор.

coutl << "Some Text " << 15 << " Other Text"; // coutl should add a linebreak

0

Решение

Создав небольшой прокси-объект, который добавляет << endl в его деструкторе:

class AddEndl
{
public:
AddEndl(std::ostream& os) : _holder(new Holder(os)) {}

template <class T>
friend std::ostream& operator<< (const AddEndl& l, const T& t)
{
return (l._holder->_os) << t;
}

private:
struct Holder {
Holder (std::ostream& os) : _os(os) {}
~Holder () { _os << std::endl; }

std::ostream& _os;
};

mutable std::shared_ptr<Holder> _holder;
}

Тогда вам нужна функция, чтобы вы получили временный:

AddEndl wrap(std::ostream& os)
{
return AddEndl(os);
}

Это должно тогда работать:

wrap(std::cout) << "Hello";

ОБНОВИТЬ:

Я перемещаю деструктор, который добавляет std::endl на внутренний объект, принадлежащий std::shared_ptr<> так что пример больше не зависит от Copy Elision.

6

Другие решения

Невозможно с просто не временным объектом, созданным в стеке & который имеет полный объем функций. Как объект узнает, что это последний из цепных вызовов << operator?

Вы можете попробовать взломать как эти

class coutl
{
public:
~coutl()
{
cout<<endl;
}

template<class T>
coutl &operator<<(const T &x)
{
cout<<x;
return *this;
}

};

int main()
{
coutl()<<"Hello"<<10<<"World";
coutl()<<"Hello"<<20<<"World";
}

Еще один подобный взлом с использованием деструктора

class myostream
{
public:
~myostream()
{
cout<<endl;
}

template<class T>
myostream &operator<<(const T &x)
{
cout<<x;
return *this;
}

};

int main()
{
{
myostream coutl;
coutl<<"Hello"<<10<<"World";
}

{
myostream coutl;
coutl<<"Hello"<<10<<"World";
}

}
1

На самом деле код

cout << "Some Text " << 15 << " Other Text" << endl;

вызывает операторские функции

// (pseudo code)
std::ostream& operator<<(std::ostream, [type] obj);

несколько раз для каждого использования << операторы.
Чтобы достичь того, чего вы хотите, вам нужно создать класс, который будет вести себя как std::ostream, но «волшебным образом» знает, когда «последний» вызов operator<< выдается и добавляет перевод строки. ИМХО это невозможно без другого объекта, который отслеживает область действия операторов.

0

coutl << "Some Text " << 15 << " Other Text"; // coutl should add a linebreak

Ваша идея не может быть реализована. По факту, cout << str1; эквивалентно cout.operator<<(str1) который возвращает ссылку на саму cout. Так cout << a << b << c; можно разрешить в ((cout << a) << b) << c; Он не знает, когда последний вызов для вставки перевода строки.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector