Проверьте, является ли объект ostream cout или ofstream, С++

Есть ли способ в С++ проверить, является ли объект ostream объектом cout или объектом ofstream?

Что-то вроде:

ostream& output(ostream& out)
{
    if (out == cout)
        return out;
    else
    {
        out << "something different because its not going to the console" << endl;
        return out;
    }
}

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

Можно ли просто дважды перегружать оператор << каждый раз с другим типом потока?

Обновлено, чтобы лучше отразить намерение.


person Jordan    schedule 23.07.2010    source источник
comment
Релевантно: stackoverflow.com/questions/366955/   -  person    schedule 23.07.2010
comment
Какова ваша мотивация для этого? Мне это кажется очень плохой идеей.   -  person Brian    schedule 23.07.2010
comment
@Brian: я добавил выше, что хочу использовать оператор << для выполнения двух разных действий в зависимости от потока, альтернативные подходы приветствуются.   -  person Jordan    schedule 23.07.2010
comment
@Jordan: Да, я знаю, что вы хотите использовать << для выполнения двух разных действий в зависимости от потока. почему ты хочешь сделать это? Мне это кажется очень плохой идеей.   -  person Brian    schedule 23.07.2010
comment
Весь смысл использования потоков заключается в том, чтобы сделать его анонимным для пункта назначения, чтобы все выглядело одинаково, независимо от того, какой тип потока вы используете. Что произойдет, если кто-то подключит файловый поток к файловому дескриптору 2 (стандартный выход в большинстве систем). Это будет совершенно другой поток, но для ОС он будет идти на консоль. В качестве альтернативы, что, если ОС подключит std::cout к файлу, это так далеко от пространства приложения, что его нельзя будет обнаружить внутри приложения.   -  person Martin York    schedule 23.07.2010
comment
Похоже, ваш реальный вопрос может заключаться в том, как определить, идет ли вывод на терминал?   -  person Cascabel    schedule 23.07.2010


Ответы (4)


Это возможно, проверив «идентификацию» потока: if ( &out == &cout ) ....

Однако я сомневаюсь в полезности этого теста. Если ваша функция может обрабатывать любой поток вывода, зачем беспокоиться о том, какой поток она использует?

person xtofl    schedule 23.07.2010
comment
Почему? Может быть, записать одно в файл, а другое в терминал. Например, используйте escape-последовательности, чтобы раскрасить вывод при записи на терминал. Хотя это не сработает, если STDOUT перенаправлен. - person atzz; 23.07.2010
comment
Вряд ли это будет работать постоянно. Вы должны приводить объекты к одному и тому же типу, прежде чем брать их адрес (в данном случае это какая-то форма общего базового типа потока). - person Martin York; 23.07.2010
comment
@Martin York: это относится и к деревьям с одним наследованием? - person xtofl; 23.07.2010
comment
@sehe: я этого не знал. Что вы можете сделать в этом случае? - person xtofl; 14.03.2011
comment
@sehe: кстати, что является буфером потока с псевдонимом? (cfr stackoverflow.com/questions/5296484/) - person xtofl; 14.03.2011
comment
Я имел в виду совместное использование/псевдоним rdbuf(): см. мой собственный более ранний ответ stackoverflow.com/questions/3318714/ - person sehe; 14.03.2011

Вы определенно продвинетесь дальше, проверив подлинность потокового буфера.

if (s.rdbuf() == std::cout.rdbuf())

Это связано с тем, что перекрестно назначать потоки/псевдонимы для буферов тривиально просто, см. http://www.cplusplus.com/reference/iostream/ios/rdbuf/ и книгу Джосуттиса

person sehe    schedule 13.03.2011
comment
Так что это то, что я легко назвал «псевдонимом» буфера потока. Я предполагаю, что это было не слишком ясно, поэтому я отредактировал свои комментарии, чтобы быть более ясным. - person sehe; 14.03.2011

Похоже, что вы действительно хотите знать, не является ли поток cout, а прикреплен ли базовый файловый дескриптор к терминалу? Если это так, вам нужен базовый файловый дескриптор. К сожалению, вы не можете получить это из iostream. Если есть возможность использовать cstdio вместо iostream, то можно. Если у вас есть дескриптор файла, определить, пишете ли вы в терминал, просто, как посмотреть, возвращает ли tcgetattr() -1.

Кроме того, не позволяйте никому говорить вам, что вы не реализуете некоторые функции, которые вам нужны, потому что это запятнает чистоту какой-то дырявой абстракции. Если вам действительно нужно другое поведение, сделайте то, что вам нужно сделать, чтобы создать эту функциональность.

person frankc    schedule 23.07.2010

Я считаю изменение способа потоковой передачи на основе объекта, который вы транслируете, ужасной идеей, которая полностью игнорирует весь смысл того, как должны работать потоковые объекты. Итак, я бы создал класс-член или функцию, которая возвращает объект типа, который по-разному обрабатывает поток. Так, например, если вы хотите предоставить раскрашенный поток, вы должны вызвать:

std::cout << myclass.colorstreamer << endl;

Изменить:

Ваше предложение по обработке потоков — плохая идея, потому что вы понятия не имеете, как другие люди будут использовать ваш код. Совершенно не интуитивно понятно, что поток ведет себя по-разному в зависимости от того, какой объект выполняет потоковую передачу. Я сравниваю это с функцией, которая возвращает разные результаты в зависимости от того, кто ее вызвал, а не в зависимости от ее аргументов, хотя я признаю, что технически поток является аргументом.

Что касается того, как сделать это таким образом, один из способов — создать colorstreamer, сделать этот новый класс членом myclass и сделать myclass членом colorstreamer, а затем сделать потокового оператора colorstreamer другом myclass. Меня больше беспокоит семантика вызова функции (т. е. использование .colorstreamer для управления потоком, а не использование самого потока), чем то, как ее реализовать. Мое предложение о том, как это реализовать, вполне возможно, плохой способ сделать это; мой С++ ржавый.

person Brian    schedule 23.07.2010
comment
Не могли бы вы подробнее рассказать, почему это плохая идея, и не могли бы вы более конкретно указать, как подойти к проблеме по-своему? - person Jordan; 23.07.2010
comment
@Jordan: отредактировано, чтобы ответить на ваши вопросы, хотя я думаю, что комментарий Мартина Йорка к вашему вопросу (т. Е. Весь смысл использования потоков ...) - лучшая формулировка того, почему это плохая идея. - person Brian; 23.07.2010