加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 确保参数是控制台的输出流

发布时间:2020-12-16 07:33:09 所属栏目:百科 来源:网络整理
导读:我正在尝试制作一个颜色的流操纵器,用于输出到控制台.它工作,改变文本和背景的颜色: std::cout ConColor::Color::FgBlue 123 "abc"; //text is blue,sticky 问题在于签名: std::ostream FgBlue(std::ostream ); 此签名允许派生类,例如std :: ostringstream
我正在尝试制作一个颜色的流操纵器,用于输出到控制台.它工作,改变文本和背景的颜色:

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一起使用.

解决方法

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

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特性.

要检测stdout是否通过管道传输到文件(当然只能在运行时检测到),请使用isatty;见how to use isatty() on cout,or can I assume that cout == file descriptor 1?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读