本文介绍了粘性自定义流操纵器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 限时删除!! 如何实现我自己的自定义流操纵器,使其是粘性的。例如,我想将整数转换为二进制,以便:How do I implement my own custom stream manipulator so that it is sticky. For example, I want to convert integers to binary such that:cout << "decimal of 4: " << 4 << "\ndecimal of 4: " << 4 << binary << "\nbinary of 4: " << 4 << "\nbinary of 4: " << 4 << nobinary << "\ndecimal of 4: " << 4 << "\ndecimal of 4: " << 4 << endl;会返回:decimal of 4: 4decimal of 4: 4binary of 4: 100binary of 4: 100decimal of 4: 4decimal of 4: 4推荐答案有点涉及。为了使其易于理解,我将从基本的东西开始:为用户定义的类型使用自定义格式化标志。Doing the whole things is a bit involved. To make it comprehensible, I'll start with the basic stuff: Using custom formatting flags for user-defined types. Custom formatting of integers will follow below. IOStream类从 std :: ios_base 中获得[间接]两个数据存储: std :: ios_base :: iword()和 std :: ios_base :: pword() int s和 void * 。使用 std :: ios_base :: pword()保存分配的内存是不平凡的,幸运的是,这个相对简单的用例不需要。要使用这两个函数都返回一个非 const 引用对应的类型,你通常使用 std :: ios_base :: xalloc )一次,并在您需要访问自定义格式标记时使用它。当您使用 iword()或 pword()访问一个值时,它将初始化为零。为了把事情放在一起,这里是一个小程序演示这个:The IOStream classes derive [indirectly] from std::ios_base which provides two stores for data: std::ios_base::iword() and std::ios_base::pword() for ints and void*, respectively. Maintaining allocated memory stored with std::ios_base::pword() is non-trivial and, fortunately, not needed for this relatively simple use-case. To use these function which both return a non-const reference to the corresponding type, you normally allocate an index using std::ios_base::xalloc() once in your program and use it whenever you need to access your custom formatting flags. When you access a value with iword() or pword() initially it will be zero initialized. To put things together, here is a small program demonstrating this:#include <iostream>static int const index = std::ios_base::xalloc();std::ostream& custom(std::ostream& stream) { stream.iword(index) = 1; return stream;}std::ostream& nocustom(std::ostream& stream) { stream.iword(index) = 0; return stream;}struct mytype {};std::ostream& operator<< (std::ostream& out, mytype const&) { return out << "custom-flag=" << out.iword(index);}int main(){ std::cout << mytype() << '\n'; std::cout << custom; std::cout << mytype() << '\n'; std::cout << nocustom; std::cout << mytype() << '\n';}现在, int like 4 不是用户定义类型,并且已经为这些类型定义了输出运算符。幸运的是,你可以使用facet,更具体地使用 std :: num_put< char> 来自定义整数的格式。现在,为此,您需要执行一些步骤:Now, an int like 4 isn't a user-define type and there is already an output operator defined for these. Fortunately, you can customize the way integers get formatted using facets, more specifically using std::num_put<char>. Now, to do so you need to do a number of steps: 从 std :: num_put< ; char> 并覆盖您要赋予其专门行为的 do_put()成员。 创建 )具有新 std :: locale 的流。Derive a class from std::num_put<char> and override the do_put() members you want to give specialized behavior to.Create a std::locale object using the newly create facet.std::ios_base::imbue() the stream with the new std::locale. $ b b 为了让用户更好用,你可能需要用一个合适的 std :: num_put< end来创建一个新的 std :: locale ; char> facet当使用操纵器时。但是,在这样做之前,让我们先创建一个合适的facet:To make things nicer for the user, you might want to conjure up a new std::locale with a suitable std::num_put<char> facet when the manipulator is used. However, before doing so, let's start off with creating a suitable facet:#include <bitset>#include <iostream>#include <limits>#include <locale>static int const index = std::ios_base::xalloc();class num_put : public std::num_put<char>{protected: iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill, long v) const { if (!fmt.iword(index)) { return std::num_put<char>::do_put(to, fmt, fill, v); } else { std::bitset<std::numeric_limits<long>::digits> bits(v); size_t i(bits.size()); while (1u < i && !bits[i - 1]) { --i; } for (; 0u < i; --i, ++to) { *to = bits[i - 1]? '1': '0'; } return to; } }#if 0 // These might need to be added, too: iter_type do_put(iter_type, std::ios_base&, char_type, long long) const; iter_type do_put(iter_type, std::ios_base&, char_type, unsigned long) const; iter_type do_put(iter_type, std::ios_base&, char_type, unsigned long long) const;#endif};std::ostream& custom(std::ostream& stream) { stream.iword(index) = 1; return stream;}std::ostream& nocustom(std::ostream& stream) { stream.iword(index) = 0; return stream;}int main(){ std::locale loc(std::locale(), new num_put); std::cout.imbue(loc); std::cout << 13 << '\n'; std::cout << custom; std::cout << 13 << '\n'; std::cout << nocustom; std::cout << 13 << '\n';}有点丑的是必须 imbue()使用自定义操纵器的自定义 std :: locale 为了摆脱这个,我们可以确保自定义facet安装在使用的 std :: locale ,如果不是,只是安装它,当设置标志:What is a bit ugly is that it necessary to imbue() the custom std::locale to use the custom manipulator. To get rid of this, we can just make sure the custom facet is installed in the used std::locale and, if it is not, just install it when setting the flag:std::ostream& custom(std::ostream& stream) { if (!stream.iword(index) && 0 == dynamic_cast<num_put const*>( &std::use_facet<std::num_put<char> >(stream.getloc()))) { stream.imbue(std::locale(stream.getloc(), new num_put)); } stream.iword(index) = 1; return stream;}现在剩下的还是重写不同的 do_put()成员与各种无符号类型以及 long long 这是一个练习。What is now left is to also override the different do_put() members to work properly with the various unsigned types and with long long but this is left as an exercise. 这篇关于粘性自定义流操纵器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 1403页,肝出来的..
09-06 17:56