Я пытаюсь сделать манипулятор потока для цвета для использования с выводом на консоль. Работает, меняя цвет текста и фона:
std::cout << ConColor::Color::FgBlue << 123 << "abc"; //text is blue, sticky
Проблема с подписью:
std::ostream &FgBlue(std::ostream &);
Эта сигнатура также допускает производные классы, такие как std::ostringstream
, но нет возможности изменить цвет строкового потока. Функция изменила бы цвет консоли независимо от того, была ли она вызвана с таким аргументом.
Поэтому я хочу, чтобы аргумент был чем-то вроде std::cout
, std::wcout
и т. д. Я бы предпочел, чтобы он был общим на тот случай, если в будущем стандарте будет добавлено больше объектов std::ostream
.
Я пробовал много вещей, связанных с std::is_same
и std::is_base_of
, когда первый не работал, просто чтобы в конце концов понять, что это бессмысленно, потому что любой тип аргумента, наследуемый от std::basic_ostream<>
, будет приведен к типу, с которым я сравниваю, при передаче в функцию, давая ложные срабатывания.
Это в конечном итоге привело меня к моему ответу ниже (вариативные аргументы шаблона шаблона? Вау, это много!), Однако есть пара проблем:
- Компилятор должен поддерживать вариативные шаблоны. Я бы предпочел, чтобы решение работало на MSVC.
- Компилятор выдает загадочные ошибки в случае, если используется производный класс с другим количеством аргументов шаблона (например,
std::ostringstream
, у которого 3 вместо 2), поскольку он не проходит мимо сигнатуры функции. - Можно перенаправить stdout, скажем, в файл, поэтому, даже если аргумент равен
std::cout
, происходит то же самое, что и в случае stringstream.
Я призываю людей публиковать любые другие решения, надеюсь, лучше моего, и очень надеюсь, что-то, что работает по крайней мере с VS11.