Определить модификатор ostream C++

Я генерирую сборку и хочу, чтобы весь сгенерированный код был выровнен. Это включает в себя что-то вроде cout<<"\t"<<left<<setfill(' ')<< setw(8); перед каждой инструкцией. Как я могу объявить модификатор ostream, который спасет меня от написания всего этого кода в каждой строке. Я ищу что-то вроде:

ostream mod="\t"<<left<<setfill(' ')<< setw(8); cout<<mod<<"addiu"<<"$sp, $sp, 24"<<endl;

Я знаю, что могу сделать это с помощью макроса, но я хочу знать, как я могу сделать это с объектом ostream.

2 ответа

Решение

Потоковая функция, которая принимает и возвращает std::ostream& вызовет эту функцию в потоке. Вот как определяются некоторые стандартные манипуляторы, и это самый быстрый способ создать свой собственный, если им не нужно принимать никаких аргументов:

namespace cds {
std::ostream& pad(std::ostream& os) {
    return os << '\t' << std::setfill(' ') << std::setw(8);
}
}

int main() {
    std::cout << cds::pad << "Hello" << '\n'
              << cds::pad << "World" << '\n';
}

печатает:

$ ./SO 
       Hello
       World

Как указано в комментариях, вам не нужно повторять setfill, но, поскольку вы не знаете (с точки зрения автора манипулятора), что будет вызываться в промежуточном потоке, вы также можете.


Кроме того, как я объясняю здесь, многие разработчики, в том числе и я, рассматривают возможность использования endl плохая практика.

ostream определяет перегрузку operator<< который принимает функцию потока, так что вы можете легко определить свои собственные манипуляторы:

#include <iostream>
#include <iomanip>
using namespace std;

ostream& foo(ostream& s) {
    return s << hex << setw(4) << setfill('#');
}

int main() {
    cout << foo << 42;
    return 0;
}
Другие вопросы по тегам