[ РЕДАКТИРОВАТЬ - Я давно забыл, что это было здесь, пока я не получил 2500 просмотров "заметный вопрос".Поскольку люди просматривают - в принятом ответе есть полезная информация о перегрузках, но конкретная проверка на std::endl
еще хуже, чем я предполагал в то время, и, безусловно, неправильная вещь.
По сути, эффект отstd::endl
- для вывода \n
в поток, затем сбрасывание с std::flush
.Это независимо от платформы, включая Windows, где конец строки действительно "\ r \ n".Манипулятор endl
не абстрагируется от различий между платформами и заканчивается строкой WRT, C ++ обрабатывает так же, как это делает C - переводя \n
в "\ r \ n" (для текстового режима, а не двоичного) позже.Я думал, что C ++ делает что-то другое, такое сильное предположение, что я никогда не сомневался в этом в течение двух десятилетий, но я ошибался.
Я не помню деталей, но в любом случае возможно определить ваши собственные потоки, иобеспечить альтернативный вывод (и перевод) любых символов, в которые идет поток. Все манипуляторы должны работать должным образом, за до ваш пользовательский код потока увидит получающиеся выходные символы.Таким образом, чтобы обеспечить особое поведение конца строки, следите за \n
там (который все еще находится перед переводом конца строки в текстовом файле).]
Это хакерское дело, я знаю, но недавно мне нужно было реализовать класс потока, который бы действовал в основном как стандартный поток, но который обнаруживал бы манипулятор std :: endl и в особом случае это поведение.Моя первая попытка реализации конкретного метода была ...
mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
if (p == &std::endl)
{
// Handle special case
}
else
{
m_Underlying_Stream << p;
}
return *this;
}
Проблема в том, что компилятор не знает, на какую перегрузку std::endl
я имею в виду.Я решил это следующим образом ...
mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);
const ENDL_T l_ENDL (&std::endl);
if (p == l_ENDL)
{
// Handle special case
}
else
{
m_Underlying_Stream << p;
}
return *this;
}
То есть компилятор может разрешить перегрузку в контексте инициализации (и для присваивания, как доказал другой эксперимент), но не для operator==
.
Рассматриваемый компилятор - MinGW GCC 4.4.0, но я не думаю, что это может быть проблемой компилятора.
Я осмотрелся и нашел этот вопрос ...
Как получить адрес перегруженной функции-члена?
Если в моем коде есть проблема с константой, я не знаю, куда нужно перейти отсутствующей константой.Я не вижу никаких других очевидных проблем с типами.
У меня есть смутные представления о проблемах с числом шагов, перегрузке WRT или неявном приведении, но ничего конкретного.Итак, может ли кто-нибудь четко объяснить, что не так с моим первым примером, почему вторая версия исправляет это, и как я могу безопасно указать, какую перегрузку я имею в виду, принимая адрес функции.
Кстати: я могу догадатьсянекоторым людям не понравится, когда я тестирую адрес std::endl
, и они укажут, что это хрупко - например, у кого-то может быть свой собственный манипулятор, который вызывает std::endl
, который я бы не заметилВ общем, это правда, но в этом особом случае взлом экономит много времени, а злобность просто не имеет значения.