Где определяется endl манипулятор

Мы знаем это endl это манипулятор и внутренне это поставить '\n' в буфер, а затем очистить буфер. Где endl определены? Что такое endlэто макрос или функция, или переменная, или класс, или объект? Как я могу определить свой собственный endl Манипулятор?

cout << "hello" << endl ; /*what is endl and  where it is defined */

2

Решение

std::endl это шаблон функции подписи:

template<class CharT, class Traits>
std::basic_ostream<CharT,Traits>& endl(std::basic_ostream<CharT,Traits>&);

std::basic_ostream::operator<< перегрузка std::basic_ostream<CharT,Traits>>::operator<<(std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&)) принимает функцию определенной подписи.

Когда вы делаете std::cout << std::endl, разрешение перегрузки сделано на std::endl, который определяет правильные типы шаблонов для std::endl и создает функцию. Затем он превращается в указатель и передается operator<<,

std::basic_ostream::operator<< затем вызывает функцию для рассматриваемого ostream и возвращает возвращаемое значение. Что-то вроде:

template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
std::basic_ostream<CharT, Traits>::operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&)
) {
return func(*this);
}

Но точная реализация зависит от автора библиотеки компилятора1.

std::endl заставляет печатать новую строку, а затем сообщает ostream о необходимости очистить себя. Вы можете подражать делать std::cout << std::endl; через эти две строки кода:

std::cout.put(std::cout.widen('\n'));
std::cout.flush();

Как именно std::endl Реализовано ли это до компилятора, но приведенное выше примерное приближение того, как вы могли бы написать его (естественно, в общем потоке).

Вы гарантированно имеете доступ к std::endl если ты #include <ostream>, Вы можете иметь к нему доступ, если вы включите любой другой заголовочный файл из std библиотека. Какой файл точно определяет, это снова зависит от реализации.

std::endl известен как «манипулятор IO». Этот метод предназначен для того, чтобы позволить функциям, управляющим состоянием потока io, быть «встроенными» с выходными командами путем создания цепочки << звонит вместе.

Чтобы создать свой собственный, если вы хотите, чтобы он работал с одним типом ostream, просто создайте функцию, которая принимает такого рода ostream по ссылке, и возвращает его по ссылке. Теперь это манипулятор.

Если вы хотите обработать набор потоков, создайте шаблон как:

template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>& bob(std::basic_ostream<CharT, Traits>& os)
{
return os << os.widen('b') << os.widen('o') << os.widen('b');
}

который теперь IO манипулятор, который печатает "bob", Он может делать что угодно с basic_ostream обсуждаемый.

Альтернативный план такой:

struct bob_t {
template<class OS>
OS& operator()(OS& os)const {
return os << os.widen('b') << os.widen('o') << os.widen('b');
}
template<class OS>
operator OS&(*)(OS&)() const {
return [](OS& os)->OS&{ return bob_t{}(os); };
}
};
static const bob_t bob;

где bob теперь объект, который можно использовать как манипулятор io.


1 это << перегрузка является функцией типа A->(A->A)->A, По сути, вместо передачи X в f, мы передаем X и f в <<который затем делает f(X), Чистый синтаксический сахар.

Дело в том, что std::endl этот шаблон означает, что совершенная пересылка это немного больно из-за этой техники. Я в конечном итоге определить функцию без состояния endl_t типы, с operator basic_ostream<CharT,Traits>&(*)(basic_ostream<CharT,Traits>&)()const перегрузка, поэтому я могу иногда передавать набор перегрузки через совершенные прокси-серверы пересылки.

Тогда мы можем передать весь набор перегрузки f:(A->A) в <<и «следующий слой вниз» разрешит перегрузку.

14

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

http://en.cppreference.com/w/cpp/io/manip/endl говорит:

Определено в заголовке <ostream>

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );

если я хочу написать свой собственный endl-манипулятор, какой код мне придется написать?

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

3

По вопросам рекламы [email protected]