В 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
Создав небольшой прокси-объект, который добавляет << 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.
Невозможно с просто не временным объектом, созданным в стеке & который имеет полный объем функций. Как объект узнает, что это последний из цепных вызовов << 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";
}
}
На самом деле код
cout << "Some Text " << 15 << " Other Text" << endl;
вызывает операторские функции
// (pseudo code)
std::ostream& operator<<(std::ostream, [type] obj);
несколько раз для каждого использования <<
операторы.
Чтобы достичь того, чего вы хотите, вам нужно создать класс, который будет вести себя как std::ostream
, но «волшебным образом» знает, когда «последний» вызов operator<<
выдается и добавляет перевод строки. ИМХО это невозможно без другого объекта, который отслеживает область действия операторов.
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;
Он не знает, когда последний вызов для вставки перевода строки.