react-native-windows 0.81.35 → 0.81.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +48 -2
  2. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +40 -13
  3. package/Microsoft.ReactNative/TurboModulesProvider.cpp +30 -13
  4. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  5. package/Scripts/creaternwlib.cmd +2 -2
  6. package/external/fast-float/.syncignore +0 -1
  7. package/external/fast-float/README.md +545 -0
  8. package/external/fmt/.syncignore +0 -2
  9. package/external/fmt/README.md +484 -0
  10. package/external/fmt/doc/ChangeLog-old.md +3290 -0
  11. package/external/fmt/doc/api.md +650 -0
  12. package/external/fmt/doc/fmt.css +61 -0
  13. package/external/fmt/doc/fmt.js +4 -0
  14. package/external/fmt/doc/get-started.md +222 -0
  15. package/external/fmt/doc/index.md +151 -0
  16. package/external/fmt/doc/perf.svg +1 -0
  17. package/external/fmt/doc/python-license.txt +290 -0
  18. package/external/fmt/doc/syntax.md +887 -0
  19. package/external/folly/.syncignore +2 -3
  20. package/external/folly/README.md +263 -0
  21. package/external/folly/folly/docs/AtomicHashMap.md +134 -0
  22. package/external/folly/folly/docs/Benchmark.md +310 -0
  23. package/external/folly/folly/docs/Conv.md +291 -0
  24. package/external/folly/folly/docs/Dynamic.md +220 -0
  25. package/external/folly/folly/docs/DynamicConverter.md +71 -0
  26. package/external/folly/folly/docs/Executors.md +63 -0
  27. package/external/folly/folly/docs/FBString.md +46 -0
  28. package/external/folly/folly/docs/FBVector.md +200 -0
  29. package/external/folly/folly/docs/Fbvector--graphical_solutions.png +0 -0
  30. package/external/folly/folly/docs/Format.md +177 -0
  31. package/external/folly/folly/docs/Function.md +92 -0
  32. package/external/folly/folly/docs/Futures.md +263 -0
  33. package/external/folly/folly/docs/GroupVarint.md +46 -0
  34. package/external/folly/folly/docs/Histogram.md +104 -0
  35. package/external/folly/folly/docs/MapUtils.md +80 -0
  36. package/external/folly/folly/docs/Overview.md +263 -0
  37. package/external/folly/folly/docs/PackedSyncPtr.md +77 -0
  38. package/external/folly/folly/docs/Poly.md +500 -0
  39. package/external/folly/folly/docs/ProducerConsumerQueue.md +82 -0
  40. package/external/folly/folly/docs/Rcu.md +218 -0
  41. package/external/folly/folly/docs/SmallLocks.md +24 -0
  42. package/external/folly/folly/docs/Synchronized.md +793 -0
  43. package/external/folly/folly/docs/ThreadCachedInt.md +98 -0
  44. package/external/folly/folly/docs/ThreadLocal.md +105 -0
  45. package/external/folly/folly/docs/Traits.md +161 -0
  46. package/external/folly/folly/docs/small_vector.md +64 -0
  47. package/external/folly/folly/docs/style.css +23 -0
  48. package/external/folly/static/logo.svg +1 -0
  49. package/package.json +2 -2
  50. package/templates/cpp-lib/example/metro.config.js +31 -6
  51. package/Scripts/Warm-RnwFeedCache.ps1 +0 -413
@@ -0,0 +1,310 @@
1
+ `folly/Benchmark.h`
2
+ -----------------
3
+
4
+ `folly/Benchmark.h` provides a simple framework for writing and
5
+ executing benchmarks. Currently the framework targets only
6
+ single-threaded testing (though you can internally use fork-join
7
+ parallelism and measure total run time).
8
+
9
+ ### Overview
10
+ ***
11
+
12
+ Using `folly/Benchmark.h` is very simple. Here's an example:
13
+
14
+ ``` Cpp
15
+ #include <folly/Benchmark.h>
16
+ #include <vector>
17
+ using namespace std;
18
+ using namespace folly;
19
+ BENCHMARK(insertFrontVector) {
20
+ // Let's insert 100 elements at the front of a vector
21
+ vector<int> v;
22
+ for (unsigned int i = 0; i < 100; ++i) {
23
+ v.insert(v.begin(), i);
24
+ }
25
+ }
26
+ BENCHMARK(insertBackVector) {
27
+ // Let's insert 100 elements at the back of a vector
28
+ vector<int> v;
29
+ for (unsigned int i = 0; i < 100; ++i) {
30
+ v.insert(v.end(), i);
31
+ }
32
+ }
33
+ int main() {
34
+ runBenchmarks();
35
+ }
36
+ ```
37
+
38
+ Compiling and running this code produces to the standard output:
39
+
40
+ ```
41
+ ===============================================================================
42
+ test.cpp relative ns/iter iters/s
43
+ ===============================================================================
44
+ insertFrontVector 3.84K 260.38K
45
+ insertBackVector 1.61K 622.75K
46
+ ===============================================================================
47
+ ```
48
+
49
+ Let's worry about the empty column "relative" later. The table
50
+ contains, for each benchmark, the time spent per call and the converse
51
+ number of calls per second. Numbers are represented in metric notation
52
+ (K for thousands, M for millions etc). As expected, in this example
53
+ the second function is much faster (fewer ns/iter and more iters/s).
54
+
55
+ The macro `BENCHMARK` introduces a function and also adds it to an
56
+ internal array containing all benchmarks in the system. The defined
57
+ function takes no arguments and returns `void`.
58
+
59
+ The framework calls the function many times to collect statistics
60
+ about it. Sometimes the function itself would want to do that
61
+ iteration---for example how about inserting `n` elements instead of
62
+ 100 elements? To do the iteration internally, use `BENCHMARK` with two
63
+ parameters. The second parameter is the number of iterations and is
64
+ passed by the framework down to the function. The type of the count is
65
+ implicitly `unsigned`. Consider a slightly reworked example:
66
+
67
+ ``` Cpp
68
+ #include <folly/Benchmark.h>
69
+ #include <folly/container/Foreach.h>
70
+ #include <vector>
71
+ using namespace std;
72
+ using namespace folly;
73
+ BENCHMARK(insertFrontVector, n) {
74
+ vector<int> v;
75
+ for (unsigned int i = 0; i < n; ++i) {
76
+ v.insert(v.begin(), i);
77
+ }
78
+ }
79
+ BENCHMARK(insertBackVector, n) {
80
+ vector<int> v;
81
+ for (unsigned int i = 0; i < n; ++i) {
82
+ v.insert(v.end(), i);
83
+ }
84
+ }
85
+ int main() {
86
+ runBenchmarks();
87
+ }
88
+ ```
89
+
90
+ The produced numbers are substantially different:
91
+
92
+ ```
93
+ ===============================================================================
94
+ Benchmark relative ns/iter iters/s
95
+ ===============================================================================
96
+ insertFrontVector 39.92 25.05M
97
+ insertBackVector 3.46 288.89M
98
+ ===============================================================================
99
+ ```
100
+
101
+ Now the numbers indicate the speed of one single insertion because the
102
+ framework assumed the user-defined function used internal iteration
103
+ (which it does). So inserting at the back of a vector is more than 10
104
+ times faster than inserting at the front! Speaking of comparisons...
105
+
106
+ ### Baselines
107
+ ***
108
+
109
+ Choosing one or more good baselines is a crucial activity in any
110
+ measurement. Without a baseline there is little information to derive
111
+ from the sheer numbers. If, for example, you do experimentation with
112
+ algorithms, a good baseline is often an established approach (e.g. the
113
+ built-in `std::sort` for sorting). Essentially all experimental
114
+ numbers should be compared against some baseline.
115
+
116
+ To support baseline-driven measurements, `folly/Benchmark.h` defines
117
+ `BENCHMARK_RELATIVE`, which works much like `BENCHMARK`, except it
118
+ considers the most recent lexically-occurring `BENCHMARK` a baseline,
119
+ and fills the "relative" column. Say, for example, we want to use
120
+ front insertion for a vector as a baseline and see how back insertion
121
+ compares with it:
122
+
123
+ ``` Cpp
124
+ #include <folly/Benchmark.h>
125
+ #include <folly/container/Foreach.h>
126
+ #include <vector>
127
+ using namespace std;
128
+ using namespace folly;
129
+ BENCHMARK(insertFrontVector, n) {
130
+ vector<int> v;
131
+ for (unsigned int i = 0; i < n; ++i) {
132
+ v.insert(v.begin(), i);
133
+ }
134
+ }
135
+ BENCHMARK_RELATIVE(insertBackVector, n) {
136
+ vector<int> v;
137
+ for (unsigned int i = 0; i < n; ++i) {
138
+ v.insert(v.end(), i);
139
+ }
140
+ }
141
+ int main() {
142
+ runBenchmarks();
143
+ }
144
+ ```
145
+
146
+ This program prints something like:
147
+
148
+ ```
149
+ ===============================================================================
150
+ Benchmark relative ns/iter iters/s
151
+ ===============================================================================
152
+ insertFrontVector 42.65 23.45M
153
+ insertBackVector 1208.24% 3.53 283.30M
154
+ ===============================================================================
155
+ ```
156
+
157
+ showing the 1208.24% relative speed advantage of inserting at the back
158
+ compared to front. The scale is chosen in such a way that 100% means
159
+ identical speed, numbers smaller than 100% indicate the benchmark is
160
+ slower than the baseline, and numbers greater than 100% indicate the
161
+ benchmark is faster. For example, if you see 42% that means the speed
162
+ of the benchmark is 0.42 of the baseline speed. If you see 123%, it
163
+ means the benchmark is 23% or 1.23 times faster.
164
+
165
+ To close the current benchmark group and start another, simply use
166
+ `BENCHMARK` again.
167
+
168
+ ### Ars Gratia Artis
169
+ ***
170
+
171
+ If you want to draw a horizontal line of dashes (e.g. at the end of a
172
+ group or for whatever reason), use `BENCHMARK_DRAW_LINE()`. The line
173
+ fulfills a purely aesthetic role; it doesn't interact with
174
+ measurements in any way.
175
+
176
+ ``` Cpp
177
+ BENCHMARK(foo) {
178
+ Foo foo;
179
+ foo.doSomething();
180
+ }
181
+
182
+ BENCHMARK_DRAW_LINE();
183
+
184
+ BENCHMARK(bar) {
185
+ Bar bar;
186
+ bar.doSomething();
187
+ }
188
+ ```
189
+
190
+ If you want to print arbitrary text (e.g. a comment or for whatever
191
+ reason), use `BENCHMARK_DRAW_TEXT("your text here")`. The output will
192
+ be the literal value so escape codes like `\n` or `\t` will not work.
193
+ To add multiple lines of output use multiple `BENCHMARK_DRAW_TEXT`
194
+ calls.
195
+
196
+ ``` Cpp
197
+ BENCHMARK(foo) {
198
+ Foo foo;
199
+ foo.doSomething();
200
+ }
201
+
202
+ BENCHMARK_DRAW_TEXT("Note: bar is expected to be 2x more expensive.");
203
+
204
+ BENCHMARK(bar) {
205
+ Bar bar;
206
+ bar.doSomething();
207
+ }
208
+ ```
209
+
210
+ ### Suspending a benchmark
211
+ ***
212
+
213
+ Sometimes benchmarking code must do some preparation work that is
214
+ physically inside the benchmark function, but should not take part to
215
+ its time budget. To temporarily suspend the benchmark, use the
216
+ pseudo-statement `BENCHMARK_SUSPEND` as follows:
217
+
218
+ ``` Cpp
219
+ BENCHMARK(insertBackVector, n) {
220
+ vector<int> v;
221
+ BENCHMARK_SUSPEND {
222
+ v.reserve(n);
223
+ }
224
+ for (unsigned int i = 0; i < n; ++i) {
225
+ v.insert(v.end(), i);
226
+ }
227
+ }
228
+ ```
229
+
230
+ The preallocation effected with `v.reserve(n)` will not count toward
231
+ the total run time of the benchmark.
232
+
233
+ Only the main thread should call `BENCHMARK_SUSPEND` (and of course it
234
+ should not call it while other threads are doing actual work). This is
235
+ because the timer is application-global.
236
+
237
+ If the scope introduced by `BENCHMARK_SUSPEND` is not desired, you may
238
+ want to "manually" use the `BenchmarkSuspender` type. Constructing
239
+ such an object suspends time measurement, and destroying it resumes
240
+ the measurement. If you want to resume time measurement before the
241
+ destructor, call `dismiss` against the `BenchmarkSuspender`
242
+ object. The previous example could have been written like this:
243
+
244
+ ``` Cpp
245
+ BENCHMARK(insertBackVector, n) {
246
+ BenchmarkSuspender braces;
247
+ vector<int> v;
248
+ v.reserve(n);
249
+ braces.dismiss();
250
+ for (unsigned int i = 0; i < n; ++i) {
251
+ v.insert(v.end(), i);
252
+ }
253
+ }
254
+ ```
255
+
256
+ ### `doNotOptimizeAway`
257
+ ***
258
+
259
+ Finally, the small utility function `doNotOptimizeAway` prevents
260
+ compiler optimizations that may interfere with benchmarking . Call
261
+ doNotOptimizeAway(var) against variables that you use for
262
+ benchmarking but otherwise are useless. The compiler tends to do a
263
+ good job at eliminating unused variables, and this function fools it
264
+ into thinking a variable is in fact needed. Example:
265
+
266
+ ``` Cpp
267
+ BENCHMARK(fpOps, n) {
268
+ double d = 1;
269
+ FOR_EACH_RANGE (i, 1, n) {
270
+ d += i;
271
+ d -= i;
272
+ d *= i;
273
+ d /= i;
274
+ }
275
+ doNotOptimizeAway(d);
276
+ }
277
+ ```
278
+
279
+ ### A look under the hood
280
+ ***
281
+
282
+ `folly/Benchmark.h` has a simple, systematic approach to collecting
283
+ timings.
284
+
285
+ First, it organizes measurements in several large epochs, and takes
286
+ the minimum over all epochs. Taking the minimum gives the closest
287
+ result to the real runtime. Benchmark timings are not a regular random
288
+ variable that fluctuates around an average. Instead, the real time
289
+ we're looking for is one to which there's a variety of additive noise
290
+ (i.e. there is no noise that could actually shorten the benchmark time
291
+ below its real value). In theory, taking an infinite amount of samples
292
+ and keeping the minimum is the actual time that needs
293
+ measuring. That's why the accuracy of benchmarking increases with the
294
+ number of epochs.
295
+
296
+ Clearly, in real functioning there will also be noise and a variety of
297
+ effects caused by the running context. But the noise during the
298
+ benchmark (straight setup, simple looping) is a poor model for the
299
+ noise in the real application. So taking the minimum across several
300
+ epochs is the most informative result.
301
+
302
+ Inside each epoch, the function measured is iterated an increasing
303
+ number of times until the total runtime is large enough to make noise
304
+ negligible. At that point the time is collected, and the time per
305
+ iteration is computed. As mentioned, the minimum time per iteration
306
+ over all epochs is the final result.
307
+
308
+ The timer function used is `clock_gettime` with the `CLOCK_REALTIME`
309
+ clock id. Note that you must use a recent Linux kernel (2.6.38 or
310
+ newer), otherwise the resolution of `CLOCK_REALTIME` is inadequate.
@@ -0,0 +1,291 @@
1
+ `folly/Conv.h`
2
+ -------------
3
+
4
+ `folly/Conv.h` is a one-stop-shop for converting values across
5
+ types. Its main features are simplicity of the API (only the
6
+ names `to` and `toAppend` must be memorized), speed
7
+ (folly is significantly faster, sometimes by an order of magnitude,
8
+ than comparable APIs), and correctness.
9
+
10
+ ### Synopsis
11
+ ***
12
+
13
+ All examples below are assume to have included `folly/Conv.h`
14
+ and issued `using namespace folly;` You will need:
15
+
16
+ ``` Cpp
17
+ // To format as text and append to a string, use toAppend.
18
+ fbstring str;
19
+ toAppend(2.5, &str);
20
+ CHECK_EQ(str, "2.5");
21
+
22
+ // Multiple arguments are okay, too. Just put the pointer to string at the end.
23
+ toAppend(" is ", 2, " point ", 5, &str);
24
+ CHECK_EQ(str, "2.5 is 2 point 5");
25
+
26
+ // You don't need to use fbstring (although it's much faster for conversions and in general).
27
+ std::string stdStr;
28
+ toAppend("Pi is about ", 22.0 / 7, &stdStr);
29
+ // In general, just use to<TargetType>(sourceValue). It returns its result by value.
30
+ stdStr = to<std::string>("Variadic ", "arguments also accepted.");
31
+
32
+ // to<fbstring> is 2.5x faster than to<std::string> for typical workloads.
33
+ str = to<fbstring>("Variadic ", "arguments also accepted.");
34
+ ```
35
+
36
+ ### Integral-to-integral conversion
37
+ ***
38
+
39
+ Using `to<Target>(value)` to convert one integral type to another
40
+ will behave as follows:
41
+
42
+ * If the target type can accommodate all possible values of the
43
+ source value, the value is implicitly converted. No further
44
+ action is taken. Example:
45
+
46
+ ``` Cpp
47
+ short x;
48
+ unsigned short y;
49
+ ...
50
+ auto a = to<int>(x); // zero overhead conversion
51
+ auto b = to<int>(y); // zero overhead conversion
52
+ ```
53
+
54
+ * Otherwise, `to` inserts bounds checks and throws
55
+ `std::range_error` if the target type cannot accommodate the
56
+ source value. Example:
57
+
58
+ ``` Cpp
59
+ short x;
60
+ unsigned short y;
61
+ long z;
62
+ ...
63
+ x = 123;
64
+ auto a = to<unsigned short>(x); // fine
65
+ x = -1;
66
+ a = to<unsigned short>(x); // THROWS
67
+ z = 2000000000;
68
+ auto b = to<int>(z); // fine
69
+ z += 1000000000;
70
+ b = to<int>(z); // THROWS
71
+ auto b = to<unsigned int>(z); // fine
72
+ ```
73
+
74
+ ### Anything-to-string conversion
75
+ ***
76
+
77
+ As mentioned, there are two primitives for converting anything to
78
+ string: `to` and `toAppend`. They support the same set of source
79
+ types, literally by definition (`to` is implemented in terms of
80
+ `toAppend` for all types). The call `toAppend(value, &str)`
81
+ formats and appends `value` to `str` whereas
82
+ `to<StringType>(value)` formats `value` as a `StringType` and
83
+ returns the result by value. Currently, the supported
84
+ `StringType`s are `std::string` and `fbstring`
85
+
86
+ Both `toAppend` and `to` with a string type as a target support
87
+ variadic arguments. Each argument is converted in turn. For
88
+ `toAppend` the last argument in a variadic list must be the
89
+ address of a supported string type (no need to specify the string
90
+ type as a template argument).
91
+
92
+ #### Integral-to-string conversion
93
+
94
+ Nothing special here - integrals are converted to strings in
95
+ decimal format, with a '-' prefix for negative values. Example:
96
+
97
+ ``` Cpp
98
+ auto a = to<fbstring>(123);
99
+ assert(a == "123");
100
+ a = to<fbstring>(-456);
101
+ assert(a == "-456");
102
+ ```
103
+
104
+ The conversion implementation is aggressively optimized. It
105
+ converts two digits at a time assisted by fixed-size tables.
106
+ Converting a `long` to an `fbstring` is 3.6x faster than using
107
+ `boost::lexical_cast` and 2.5x faster than using `sprintf` even
108
+ though the latter is used in conjunction with a stack-allocated
109
+ constant-size buffer.
110
+
111
+ Note that converting integral types to `fbstring` has a
112
+ particular advantage compared to converting to `std::string`
113
+ No integral type (<= 64 bits) has more than 20 decimal digits
114
+ including sign. Since `fbstring` employs the small string
115
+ optimization for up to 23 characters, converting an integral
116
+ to `fbstring` is guaranteed to not allocate memory, resulting
117
+ in significant speed and memory locality gains. Benchmarks
118
+ reveal a 2x gain on a typical workload.
119
+
120
+ #### `char` to string conversion
121
+
122
+ Although `char` is technically an integral type, most of the time
123
+ you want the string representation of `'a'` to be `"a"`, not `96`
124
+ That's why `folly/Conv.h` handles `char` as a special case that
125
+ does the expected thing. Note that `signed char` and `unsigned
126
+ char` are still considered integral types.
127
+
128
+
129
+ #### Floating point to string conversion
130
+
131
+ `folly/Conv.h` uses [V8's double conversion](http://code.google.com/p/double-conversion/)
132
+ routines. They are accurate and fast; on typical workloads,
133
+ `to<fbstring>(doubleValue)` is 1.9x faster than `sprintf` and
134
+ 5.5x faster than `boost::lexical_cast` (It is also 1.3x faster
135
+ than `to<std::string>(doubleValue)`
136
+
137
+ #### `const char*` to string conversion
138
+
139
+ For completeness, `folly/Conv.h` supports `const char*` including
140
+ i.e. string literals. The "conversion" consists, of course, of
141
+ the string itself. Example:
142
+
143
+ ``` Cpp
144
+ auto s = to<fbstring>("Hello, world");
145
+ assert(s == "Hello, world");
146
+ ```
147
+
148
+ #### Anything from string conversion (i.e. parsing)
149
+ ***
150
+
151
+ `folly/Conv.h` includes three kinds of parsing routines:
152
+
153
+ * `to<Type>(const char* begin, const char* end)` rigidly
154
+ converts the range [begin, end) to `Type` These routines have
155
+ drastic restrictions (e.g. allow no leading or trailing
156
+ whitespace) and are intended as an efficient back-end for more
157
+ tolerant routines.
158
+ * `to<Type>(stringy)` converts `stringy` to `Type` Value
159
+ `stringy` may be of type `const char*`, `StringPiece`,
160
+ `std::string`, or `fbstring` (Technically, the requirement is
161
+ that `stringy` implicitly converts to a `StringPiece`
162
+ * `to<Type>(&stringPiece)` parses with progress information:
163
+ given `stringPiece` of type `StringPiece` it parses as much
164
+ as possible from it as type `Type` and alters `stringPiece`
165
+ to remove the munched characters. This is easiest clarified
166
+ by an example:
167
+
168
+ ``` Cpp
169
+ fbstring s = " 1234 angels on a pin";
170
+ StringPiece pc(s);
171
+ auto x = to<int>(&pc);
172
+ assert(x == 1234);
173
+ assert(pc == " angels on a pin";
174
+ ```
175
+
176
+ Note how the routine ate the leading space but not the trailing one.
177
+
178
+ #### Parsing integral types
179
+
180
+ Parsing integral types is unremarkable - decimal format is
181
+ expected, optional `'+'` or `'-'` sign for signed types, but no
182
+ optional `'+'` is allowed for unsigned types. The one remarkable
183
+ element is speed - parsing typical `long` values is 6x faster than
184
+ `sscanf`. `folly/Conv.h` uses aggressive loop unrolling and
185
+ table-assisted SIMD-style code arrangement that avoids integral
186
+ division (slow) and data dependencies across operations
187
+ (ILP-unfriendly). Example:
188
+
189
+ ``` Cpp
190
+ fbstring str = " 12345 ";
191
+ assert(to<int>(str) == 12345);
192
+ str = " 12345six seven eight";
193
+ StringPiece pc(str);
194
+ assert(to<int>(&pc) == 12345);
195
+ assert(str == "six seven eight");
196
+ ```
197
+
198
+ #### Parsing floating-point types
199
+
200
+ `folly/Conv.h` uses, again, [V8's double-conversion](http://code.google.com/p/double-conversion/)
201
+ routines as back-end. The speed is 3x faster than `sscanf` and
202
+ 1.7x faster than in-home routines such as `parse<double>` But
203
+ the more important detail is accuracy - even if you do code a
204
+ routine that works faster than `to<double>` chances are it is
205
+ incorrect and will fail in a variety of corner cases. Using
206
+ `to<double>` is strongly recommended.
207
+
208
+ Note that if the string "NaN" (with any capitalization) is passed to
209
+ `to<double>` then `NaN` is returned, which can be tested for as follows:
210
+
211
+ ``` Cpp
212
+ fbstring str = "nan"; // "NaN", "NAN", etc.
213
+ double d = to<double>(str);
214
+ if (std::isnan(d)) {
215
+ // string was a valid representation of the double value NaN
216
+ }
217
+ ```
218
+
219
+ Note that passing "-NaN" (with any capitalization) to `to<double>` also returns
220
+ `NaN`.
221
+
222
+ Note that if the strings "inf" or "infinity" (with any capitalization) are
223
+ passed to `to<double>` then `infinity` is returned, which can be tested for
224
+ as follows:
225
+
226
+ ``` Cpp
227
+ fbstring str = "inf"; // "Inf", "INF", "infinity", "Infinity", etc.
228
+ double d = to<double>(str);
229
+ if (std::isinf(d)) {
230
+ // string was a valid representation of one of the double values +Infinity
231
+ // or -Infinity
232
+ }
233
+ ```
234
+
235
+ Note that passing "-inf" or "-infinity" (with any capitalization) to
236
+ `to<double>` returns `-infinity` rather than `+infinity`. The sign of the
237
+ `infinity` can be tested for as follows:
238
+
239
+ ``` Cpp
240
+ fbstring str = "-inf"; // or "inf", "-Infinity", "+Infinity", etc.
241
+ double d = to<double>(str);
242
+ if (d == std::numeric_limits<double>::infinity()) {
243
+ // string was a valid representation of the double value +Infinity
244
+ } else if (d == -std::numeric_limits<double>::infinity()) {
245
+ // string was a valid representation of the double value -Infinity
246
+ }
247
+ ```
248
+
249
+ Note that if an unparseable string is passed to `to<double>` then an exception
250
+ is thrown, rather than `NaN` being returned. This can be tested for as follows:
251
+
252
+ ``` Cpp
253
+ fbstring str = "not-a-double"; // Or "1.1.1", "", "$500.00", etc.
254
+ double d;
255
+ try {
256
+ d = to<double>(str);
257
+ } catch (const std::range_error &) {
258
+ // string could not be parsed
259
+ }
260
+ ```
261
+
262
+ Note that the empty string (`""`) is an unparseable value, and will cause
263
+ `to<double>` to throw an exception.
264
+
265
+ #### Non-throwing interfaces
266
+
267
+ `tryTo<T>` is the non-throwing variant of `to<T>`. It returns
268
+ an `Expected<T, ConversionCode>`. You can think of `Expected`
269
+ as like an `Optional<T>`, but if the conversion failed, `Expected`
270
+ stores an error code instead of a `T`.
271
+
272
+ `tryTo<T>` has similar performance as `to<T>` when the
273
+ conversion is successful. On the error path, you can expect
274
+ `tryTo<T>` to be roughly three orders of magnitude faster than
275
+ the throwing `to<T>` and to completely avoid any lock contention
276
+ arising from stack unwinding.
277
+
278
+ Here is how to use non-throwing conversions:
279
+
280
+ ``` Cpp
281
+ auto t1 = tryTo<int>(str);
282
+ if (t1.hasValue()) {
283
+ use(t1.value());
284
+ }
285
+ ```
286
+
287
+ `Expected` has a composability feature to make the above pattern simpler.
288
+
289
+ ``` Cpp
290
+ tryTo<int>(str).then([](int i) { use(i); });
291
+ ```