File: stream_converter.qbk

package info (click to toggle)
boost1.74 1.74.0-9
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 464,084 kB
  • sloc: cpp: 3,338,324; xml: 131,293; python: 33,088; ansic: 14,336; asm: 4,034; sh: 3,351; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (144 lines) | stat: -rw-r--r-- 5,542 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
[/
  Copyright (c) Vladimir Batov 2009-2016
  Distributed under the Boost Software License, Version 1.0.
  See copy at http://www.boost.org/LICENSE_1_0.txt.
]

[section:stream_converter ['boost::cnv::stream] Converter]

The purpose of the converter is to provide conversion-related formatting and locale support not available with `boost::lexical_cast`. Advantages of deploying a `std::stream`-based conversion engine are:

* availability and maturity;
* formatting and locale support;
* familiar interface and deployment;
* instant re-use of available standard manipulators (`std::hex`, `std::setprecision`, `std::skipws`, etc.);
* extendibility via custom manipulators (see [@http://www.cecalc.ula.ve/documentacion/tutoriales/PGICDK/doc/pgC++_lib/stdlibug/str_5412.htm Stream Storage for Private Use: iword, pword, and xalloc] by Rogue Wave Software).

The converter might be deployed as follows:

[stream_headers1]
[stream_example1]

[section Formatting Support]

Formatting support is provided by the underlying `std::stringstream`. Consequently, the API heavily borrows formatting metaphors from this underlying component. One such metaphor is the ['manipulator] represented by `std::hex`, `std::dec`, `std::uppercase`, `std::scientific`, etc.

The following code demonstrates how `char` and `wchar_t` strings can be read in the `std::hex` or `std::dec` format:

[stream_example2]

For batch-processing it might be more efficient to configure the converter once:

[stream_example3]

An alternative (generic) formatting interface is currently being extended and explored:

[stream_headers2]
[stream_example4]

is equivalent to the following ['std::manipulator]-based variant:

[stream_example5]

[section Numeric Base]
[stream_using]
[stream_numbase_example1]

A more generic interface is also supported:

[stream_cnv_namespace_shortcut]
[stream_numbase_example2]
[endsect]

[section Field Width, Fill Character and Adjustment]
[stream_width_example]
[endsect]

[section Leading Whitespace Characters]
[stream_using]
[stream_skipws_example]
[endsect]

[section Format of Boolean Values]
[stream_using]
[stream_boolalpha_example]
[endsect]
[endsect]

[section Locale Support]

Locale support is similar to the formatting support as demonstrated by the following example:

[stream_headers2]
[stream_locale_example1]

[endsect]
[section Supported String Types]
[section Wide String]
[wide_stream_numeric_base]
[wide_stream_skipws]
[endsect]

[section Custom String Types]

`boost::cnv::stream` accepts custom string and string-like types as input or output as long as they satisfy certain requirements. 

[stream_my_string]

When a string-like type is the source, then it needs to be a ['contiguous sequence] of the corresponding character type (`char` or `wchar_t`) accessible via `begin()` and `end()`. 

`std::stringstream` is implemented entirely in terms of `std::basic_streambuf` which, in turn, operates on a ['contiguous character sequence], also called the ['buffer] (see [@http://en.cppreference.com/w/cpp/io/basic_streambuf `std::basic_streambuf`] for details). For efficiency reasons `boost::cnv::stream` uses the provided (read-only) input string as the ['buffer] and, consequently, requires that provided input string to be a contiguous character sequence.

When a string is the target, then the described ['contiguous character sequence] requirement does not apply. Any type that provides 

 MyType::MyType(char const* beg, char const* end)
 
constructor can be deployed in type-to-string conversions.

See [link boost_convert.performance.the_bigger_picture The Bigger Picture] chapter for the discussion of potential advantages of deploying custom strings.

[endsect]
[endsect]
[section The ['Default Constructible] Type Requirement]

Due to `std::stream` design it requires an ['initialized] temporary storage of ['TypeOut] type to put the result of the requested conversion to. Conceptually `boost::cnv::cstream` achieves that with:

 istream_type& istream = stream_;
 TypeOut        result = boost::make_default<TypeOut>();

 istream >> result;

The temporary storage `result` is initialized with `boost::make_default()` the default implementation of which is

 namespace boost
 {
    template<typename T> T make_default() { return T(); }
 }

Consequently,

[note [*By default] the `boost::cnv::cstream` and `boost::cnv::wstream` converters require the ['TypeOut] type to be [@http://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['Default Constructible]].]

That said, a well-designed type (in my opinion, anyway) should only have meaningful and unambiguous constructors... and the default constructor is not always and necessarily one of them. Consider the following as one such example:

[direction_declaration]
[direction_stream_operators]

The `direction` type has no default state. It is not [@http://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['Default Constructible]] and, consequently, the following does not compile:

 direction dir1 = convert<direction>(str, cnv).value(); // Does not compile
 direction dir2 = lexical_cast<direction>(str);         // Does not compile

However, ['Boost.Convert] is able to handle such a type with little help from the user -- the instructions ['how] to create that mentioned temporary storage:

[direction_declaration_make_default]

Now such class can be deployed with `boost::cnv::cstream`:

 direction dir1 = convert<direction>(str, cnv).value(); // Compiles
 direction dir2 = lexical_cast<direction>(str); // Does not compile

[endsect]
[endsect]