确保参数是控制台的输出流 [英] Ensure argument is an output stream for the console

查看:165
本文介绍了确保参数是控制台的输出流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图做一个流操纵器的颜色使用输出到控制台。它的工作原理,改变文本和背景的颜色:

I'm trying to make a stream manipulator for colour for use with output to the console. It works, changing the colour of text and the background:

std::cout << ConColor::Color::FgBlue << 123 << "abc"; //text is blue, sticky

问题是签名:

std::ostream &FgBlue(std::ostream &);

此签名允许派生类,例如 std :: ostringstream ,但是没有办法改变字符串流的颜色。该函数将改变控制台的颜色,不管它是否使用这样的参数调用。

This signature allows for derived classes, such as std::ostringstream as well, but there is no way to change the colour of a string stream. The function would change the colour of the console regardless if it was called with such an argument.

因此,我想确保参数是 std :: cout std :: wcout 等。我更喜欢一般在更多 std :: ostream 对象添加到未来标准。

Therefore, I want to ensure the argument is something along the lines of std::cout, std::wcout, etc. I would prefer it be general in the case that more std::ostream objects are added in a future standard.

我尝试了许多涉及 std :: is_same std :: is_base_of ,当前者不工作,只是最终意识到这是无意义的,因为任何参数类型继承自 std :: basic_ostream<> 将被转换为我传递给函数时比较的类型,给出假阳性。

I tried many things involving std::is_same and std::is_base_of, when the former wouldn't work, just to eventually realize that it was pointless because any argument type inheriting from std::basic_ostream<> will be casted to the type I'm comparing against when passed to the function, giving false positives.

这最终导致我的回答如下(variadic模板模板参数但是,还有一些问题:

This eventually led me to my answer below (variadic template template arguments? Wow, that's a mouthful!) There are a couple problems, however:


  • 编译器必须支持可变参数模板。

  • 如果派生类拥有不同数量的模板参数(例如 std:),编译器会产生隐藏错误。 :ostringstream ,它有3而不是2),因为它没有通过函数签名。

  • 可以重定向stdout,到文件,因此即使参数 std :: cout ,也会发生与stringstream情况相同的情况。

  • The compiler must support variadic templates. I would prefer the solution work on MSVC.
  • The compiler gives cryptic errors in the case that a derived class with a different number of template arguments (such as std::ostringstream, which has 3 instead of 2) is used, as it doesn't get past the function signature.
  • It's possible to redirect stdout, say, to a file, so even if the argument is std::cout, the same thing as the stringstream case happens.

我鼓励人们发布任何其他的解决方案,希望比我更好,真正希望至少VS11工作的东西。

I encourage people to post any other solutions, hopefully better than mine, and really hopefully something that works with at least VS11.

推荐答案

这里是检测 std :: basic_ostream 实例化的特征:

Here's a trait for detecting std::basic_ostream instantiations:

template<typename T> struct is_basic_ostream {
  template<typename U, typename V>
  static char (&impl(std::basic_ostream<U, V> *))[
    std::is_same<T, std::basic_ostream<U, V>>::value ? 2 : 1];
  static char impl(...);
  static constexpr bool value = sizeof(impl((T *)0)) == 2;
};

使用方法:

template<typename T>
void foo(T &) {
  static_assert(is_basic_ostream<T>::value,
    "Argument must be of type std::basic_ostream<T, U>.");
}



我们使用模板参数推导来推断模板参数) basic_ostream 基类(如果有)。作为更一般的解决方案,用单个可变参数替换 U V 将允许写一个通用 is_instantiation_of trait在支持可变参数模板参数的编译器上。

We use template argument deduction to infer the template parameters on the (non-proper) basic_ostream base class, if any. As a more general solution, replacing U and V with a single variadic parameter would allow writing a generic is_instantiation_of trait on compilers that support variadic template parameters.

要检测stdout是否管道到一个文件(只能在运行时检测,当然)使用 isatty ;请参阅如何在cout上使用isatty(),或者我可以假设cout ==文件描述符1?

To detect whether stdout is piped to a file (which can only be detected at runtime, of course) use isatty; see how to use isatty() on cout, or can I assume that cout == file descriptor 1?

这篇关于确保参数是控制台的输出流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆