xref: /aosp_15_r20/external/icu/libicu/cts_headers/unicode/numberrangeformatter.h (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1 // © 2018 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 #ifndef __NUMBERRANGEFORMATTER_H__
5 #define __NUMBERRANGEFORMATTER_H__
6 
7 #include "unicode/utypes.h"
8 
9 #if U_SHOW_CPLUSPLUS_API
10 
11 #if !UCONFIG_NO_FORMATTING
12 
13 #include <atomic>
14 #include "unicode/appendable.h"
15 #include "unicode/fieldpos.h"
16 #include "unicode/formattedvalue.h"
17 #include "unicode/fpositer.h"
18 #include "unicode/numberformatter.h"
19 #include "unicode/unumberrangeformatter.h"
20 
21 /**
22  * \file
23  * \brief C++ API: Library for localized formatting of number, currency, and unit ranges.
24  *
25  * The main entrypoint to the formatting of ranges of numbers, including currencies and other units of measurement.
26  * <p>
27  * Usage example:
28  * <p>
29  * <pre>
30  * NumberRangeFormatter::with()
31  *     .identityFallback(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE)
32  *     .numberFormatterFirst(NumberFormatter::with().adoptUnit(MeasureUnit::createMeter()))
33  *     .numberFormatterSecond(NumberFormatter::with().adoptUnit(MeasureUnit::createKilometer()))
34  *     .locale("en-GB")
35  *     .formatFormattableRange(750, 1.2, status)
36  *     .toString(status);
37  * // => "750 m - 1.2 km"
38  * </pre>
39  * <p>
40  * Like NumberFormatter, NumberRangeFormatter instances (i.e., LocalizedNumberRangeFormatter
41  * and UnlocalizedNumberRangeFormatter) are immutable and thread-safe. This API is based on the
42  * <em>fluent</em> design pattern popularized by libraries such as Google's Guava.
43  *
44  * @author Shane Carr
45  */
46 
47 
48 U_NAMESPACE_BEGIN
49 
50 // Forward declarations:
51 class PluralRules;
52 
53 namespace number {  // icu::number
54 
55 // Forward declarations:
56 class UnlocalizedNumberRangeFormatter;
57 class LocalizedNumberRangeFormatter;
58 class FormattedNumberRange;
59 
60 namespace impl {
61 
62 // Forward declarations:
63 struct RangeMacroProps;
64 class DecimalQuantity;
65 class UFormattedNumberRangeData;
66 class NumberRangeFormatterImpl;
67 struct UFormattedNumberRangeImpl;
68 
69 } // namespace impl
70 
71 /**
72  * \cond
73  * Export an explicit template instantiation. See datefmt.h
74  * (When building DLLs for Windows this is required.)
75  */
76 #if U_PLATFORM == U_PF_WINDOWS && !defined(U_IN_DOXYGEN) && !defined(U_STATIC_IMPLEMENTATION)
77 } // namespace icu::number
78 U_NAMESPACE_END
79 
80 template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>;
81 
82 U_NAMESPACE_BEGIN
83 namespace number {  // icu::number
84 #endif
85 /** \endcond */
86 
87 // Other helper classes would go here, but there are none.
88 
89 namespace impl {  // icu::number::impl
90 
91 // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
92 /** @internal */
93 struct U_I18N_API RangeMacroProps : public UMemory {
94     /** @internal */
95     UnlocalizedNumberFormatter formatter1; // = NumberFormatter::with();
96 
97     /** @internal */
98     UnlocalizedNumberFormatter formatter2; // = NumberFormatter::with();
99 
100     /** @internal */
101     bool singleFormatter = true;
102 
103     /** @internal */
104     UNumberRangeCollapse collapse = UNUM_RANGE_COLLAPSE_AUTO;
105 
106     /** @internal */
107     UNumberRangeIdentityFallback identityFallback = UNUM_IDENTITY_FALLBACK_APPROXIMATELY;
108 
109     /** @internal */
110     Locale locale;
111 
112     // NOTE: Uses default copy and move constructors.
113 
114     /**
115      * Check all members for errors.
116      * @internal
117      */
118     bool copyErrorTo(UErrorCode &status) const {
119         return formatter1.copyErrorTo(status) || formatter2.copyErrorTo(status);
120     }
121 };
122 
123 } // namespace impl
124 
125 /**
126  * An abstract base class for specifying settings related to number formatting. This class is implemented by
127  * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for
128  * public subclassing.
129  */
130 template<typename Derived>
131 class U_I18N_API NumberRangeFormatterSettings {
132   public:
133     /**
134      * Sets the NumberFormatter instance to use for the numbers in the range. The same formatter is applied to both
135      * sides of the range.
136      * <p>
137      * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
138      * NumberRangeFormatter will be used.
139      *
140      * @param formatter
141      *            The formatter to use for both numbers in the range.
142      * @return The fluent chain.
143      * @stable ICU 63
144      */
145     Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) const &;
146 
147     /**
148      * Overload of numberFormatterBoth() for use on an rvalue reference.
149      *
150      * @param formatter
151      *            The formatter to use for both numbers in the range.
152      * @return The fluent chain.
153      * @see #numberFormatterBoth
154      * @stable ICU 63
155      */
156     Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) &&;
157 
158     /**
159      * Overload of numberFormatterBoth() for use on an rvalue reference.
160      *
161      * @param formatter
162      *            The formatter to use for both numbers in the range.
163      * @return The fluent chain.
164      * @see #numberFormatterBoth
165      * @stable ICU 63
166      */
167     Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) const &;
168 
169     /**
170      * Overload of numberFormatterBoth() for use on an rvalue reference.
171      *
172      * @param formatter
173      *            The formatter to use for both numbers in the range.
174      * @return The fluent chain.
175      * @see #numberFormatterBoth
176      * @stable ICU 63
177      */
178     Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) &&;
179 
180     /**
181      * Sets the NumberFormatter instance to use for the first number in the range.
182      * <p>
183      * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
184      * NumberRangeFormatter will be used.
185      *
186      * @param formatterFirst
187      *            The formatter to use for the first number in the range.
188      * @return The fluent chain.
189      * @stable ICU 63
190      */
191     Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) const &;
192 
193     /**
194      * Overload of numberFormatterFirst() for use on an rvalue reference.
195      *
196      * @param formatterFirst
197      *            The formatter to use for the first number in the range.
198      * @return The fluent chain.
199      * @see #numberFormatterFirst
200      * @stable ICU 63
201      */
202     Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) &&;
203 
204     /**
205      * Overload of numberFormatterFirst() for use on an rvalue reference.
206      *
207      * @param formatterFirst
208      *            The formatter to use for the first number in the range.
209      * @return The fluent chain.
210      * @see #numberFormatterFirst
211      * @stable ICU 63
212      */
213     Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) const &;
214 
215     /**
216      * Overload of numberFormatterFirst() for use on an rvalue reference.
217      *
218      * @param formatterFirst
219      *            The formatter to use for the first number in the range.
220      * @return The fluent chain.
221      * @see #numberFormatterFirst
222      * @stable ICU 63
223      */
224     Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) &&;
225 
226     /**
227      * Sets the NumberFormatter instance to use for the second number in the range.
228      * <p>
229      * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
230      * NumberRangeFormatter will be used.
231      *
232      * @param formatterSecond
233      *            The formatter to use for the second number in the range.
234      * @return The fluent chain.
235      * @stable ICU 63
236      */
237     Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) const &;
238 
239     /**
240      * Overload of numberFormatterSecond() for use on an rvalue reference.
241      *
242      * @param formatterSecond
243      *            The formatter to use for the second number in the range.
244      * @return The fluent chain.
245      * @see #numberFormatterSecond
246      * @stable ICU 63
247      */
248     Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) &&;
249 
250     /**
251      * Overload of numberFormatterSecond() for use on an rvalue reference.
252      *
253      * @param formatterSecond
254      *            The formatter to use for the second number in the range.
255      * @return The fluent chain.
256      * @see #numberFormatterSecond
257      * @stable ICU 63
258      */
259     Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) const &;
260 
261     /**
262      * Overload of numberFormatterSecond() for use on an rvalue reference.
263      *
264      * @param formatterSecond
265      *            The formatter to use for the second number in the range.
266      * @return The fluent chain.
267      * @see #numberFormatterSecond
268      * @stable ICU 63
269      */
270     Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) &&;
271 
272     /**
273      * Sets the aggressiveness of "collapsing" fields across the range separator. Possible values:
274      * <p>
275      * <ul>
276      * <li>ALL: "3-5K miles"</li>
277      * <li>UNIT: "3K - 5K miles"</li>
278      * <li>NONE: "3K miles - 5K miles"</li>
279      * <li>AUTO: usually UNIT or NONE, depending on the locale and formatter settings</li>
280      * </ul>
281      * <p>
282      * The default value is AUTO.
283      *
284      * @param collapse
285      *            The collapsing strategy to use for this range.
286      * @return The fluent chain.
287      * @stable ICU 63
288      */
289     Derived collapse(UNumberRangeCollapse collapse) const &;
290 
291     /**
292      * Overload of collapse() for use on an rvalue reference.
293      *
294      * @param collapse
295      *            The collapsing strategy to use for this range.
296      * @return The fluent chain.
297      * @see #collapse
298      * @stable ICU 63
299      */
300     Derived collapse(UNumberRangeCollapse collapse) &&;
301 
302     /**
303      * Sets the behavior when the two sides of the range are the same. This could happen if the same two numbers are
304      * passed to the formatFormattableRange function, or if different numbers are passed to the function but they
305      * become the same after rounding rules are applied. Possible values:
306      * <p>
307      * <ul>
308      * <li>SINGLE_VALUE: "5 miles"</li>
309      * <li>APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before
310      * rounding was applied</li>
311      * <li>APPROXIMATELY: "~5 miles"</li>
312      * <li>RANGE: "5-5 miles" (with collapse=UNIT)</li>
313      * </ul>
314      * <p>
315      * The default value is APPROXIMATELY.
316      *
317      * @param identityFallback
318      *            The strategy to use when formatting two numbers that end up being the same.
319      * @return The fluent chain.
320      * @stable ICU 63
321      */
322     Derived identityFallback(UNumberRangeIdentityFallback identityFallback) const &;
323 
324     /**
325      * Overload of identityFallback() for use on an rvalue reference.
326      *
327      * @param identityFallback
328      *            The strategy to use when formatting two numbers that end up being the same.
329      * @return The fluent chain.
330      * @see #identityFallback
331      * @stable ICU 63
332      */
333     Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&;
334 
335     /**
336      * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer
337      * wrapping a heap-allocated copy of the current object.
338      *
339      * This is equivalent to new-ing the move constructor with a value object
340      * as the argument.
341      *
342      * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
343      *         nullptr on failure.
344      * @stable ICU 64
345      */
346     LocalPointer<Derived> clone() const &;
347 
348     /**
349      * Overload of clone for use on an rvalue reference.
350      *
351      * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
352      *         nullptr on failure.
353      * @stable ICU 64
354      */
355     LocalPointer<Derived> clone() &&;
356 
357     /**
358      * Sets the UErrorCode if an error occurred in the fluent chain.
359      * Preserves older error codes in the outErrorCode.
360      * @return true if U_FAILURE(outErrorCode)
361      * @stable ICU 63
362      */
363     UBool copyErrorTo(UErrorCode &outErrorCode) const {
364         if (U_FAILURE(outErrorCode)) {
365             // Do not overwrite the older error code
366             return true;
367         }
368         fMacros.copyErrorTo(outErrorCode);
369         return U_FAILURE(outErrorCode);
370     }
371 
372     // NOTE: Uses default copy and move constructors.
373 
374   private:
375     impl::RangeMacroProps fMacros;
376 
377     // Don't construct me directly!  Use (Un)LocalizedNumberFormatter.
378     NumberRangeFormatterSettings() = default;
379 
380     friend class LocalizedNumberRangeFormatter;
381     friend class UnlocalizedNumberRangeFormatter;
382 };
383 
384 // Explicit instantiations in source/i18n/numrange_fluent.cpp.
385 // (MSVC treats imports/exports of explicit instantiations differently.)
386 #ifndef _MSC_VER
387 extern template class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
388 extern template class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>;
389 #endif
390 
391 /**
392  * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified.
393  *
394  * Instances of this class are immutable and thread-safe.
395  *
396  * @see NumberRangeFormatter
397  * @stable ICU 63
398  */
399 class U_I18N_API UnlocalizedNumberRangeFormatter
400         : public NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>, public UMemory {
401 
402   public:
403     /**
404      * Associate the given locale with the number range formatter. The locale is used for picking the
405      * appropriate symbols, formats, and other data for number display.
406      *
407      * @param locale
408      *            The locale to use when loading data for number formatting.
409      * @return The fluent chain.
410      * @stable ICU 63
411      */
412     LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &;
413 
414     /**
415      * Overload of locale() for use on an rvalue reference.
416      *
417      * @param locale
418      *            The locale to use when loading data for number formatting.
419      * @return The fluent chain.
420      * @see #locale
421      * @stable ICU 63
422      */
423     LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&;
424 
425     /**
426      * Default constructor: puts the formatter into a valid but undefined state.
427      *
428      * @stable ICU 63
429      */
430     UnlocalizedNumberRangeFormatter() = default;
431 
432     /**
433      * Returns a copy of this UnlocalizedNumberRangeFormatter.
434      * @stable ICU 63
435      */
436     UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other);
437 
438     /**
439      * Move constructor:
440      * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
441      * @stable ICU 63
442      */
443     UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) noexcept;
444 
445     /**
446      * Copy assignment operator.
447      * @stable ICU 63
448      */
449     UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other);
450 
451     /**
452      * Move assignment operator:
453      * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
454      * @stable ICU 63
455      */
456     UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) noexcept;
457 
458   private:
459     explicit UnlocalizedNumberRangeFormatter(
460             const NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>& other);
461 
462     explicit UnlocalizedNumberRangeFormatter(
463             NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) noexcept;
464 
465     explicit UnlocalizedNumberRangeFormatter(const impl::RangeMacroProps &macros);
466 
467     explicit UnlocalizedNumberRangeFormatter(impl::RangeMacroProps &&macros);
468 
469     // To give the fluent setters access to this class's constructor:
470     friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
471 
472     // To give NumberRangeFormatter::with() access to this class's constructor:
473     friend class NumberRangeFormatter;
474 
475     // To give LNRF::withoutLocale() access to this class's constructor:
476     friend class LocalizedNumberRangeFormatter;
477 };
478 
479 /**
480  * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available.
481  *
482  * Instances of this class are immutable and thread-safe.
483  *
484  * @see NumberFormatter
485  * @stable ICU 63
486  */
487 class U_I18N_API LocalizedNumberRangeFormatter
488         : public NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>, public UMemory {
489   public:
490     /**
491      * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting
492      * chain.
493      *
494      * @param first
495      *            The first number in the range, usually to the left in LTR locales.
496      * @param second
497      *            The second number in the range, usually to the right in LTR locales.
498      * @param status
499      *            Set if an error occurs while formatting.
500      * @return A FormattedNumberRange object; call .toString() to get the string.
501      * @stable ICU 63
502      */
503     FormattedNumberRange formatFormattableRange(
504         const Formattable& first, const Formattable& second, UErrorCode& status) const;
505 
506 #ifndef U_HIDE_DRAFT_API
507     /**
508      * Disassociate the locale from this formatter.
509      *
510      * @return The fluent chain.
511      * @draft ICU 75
512      */
513     UnlocalizedNumberRangeFormatter withoutLocale() const &;
514 
515     /**
516      * Overload of withoutLocale() for use on an rvalue reference.
517      *
518      * @return The fluent chain.
519      * @see #withoutLocale
520      * @draft ICU 75
521      */
522     UnlocalizedNumberRangeFormatter withoutLocale() &&;
523 #endif // U_HIDE_DRAFT_API
524 
525     /**
526      * Default constructor: puts the formatter into a valid but undefined state.
527      *
528      * @stable ICU 63
529      */
530     LocalizedNumberRangeFormatter() = default;
531 
532     /**
533      * Returns a copy of this LocalizedNumberRangeFormatter.
534      * @stable ICU 63
535      */
536     LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other);
537 
538     /**
539      * Move constructor:
540      * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
541      * @stable ICU 63
542      */
543     LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) noexcept;
544 
545     /**
546      * Copy assignment operator.
547      * @stable ICU 63
548      */
549     LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other);
550 
551     /**
552      * Move assignment operator:
553      * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
554      * @stable ICU 63
555      */
556     LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) noexcept;
557 
558 #ifndef U_HIDE_INTERNAL_API
559 
560     /**
561      * @param results
562      *            The results object. This method will mutate it to save the results.
563      * @param equalBeforeRounding
564      *            Whether the number was equal before copying it into a DecimalQuantity.
565      *            Used for determining the identity fallback behavior.
566      * @param status
567      *            Set if an error occurs while formatting.
568      * @internal
569      */
570     void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding,
571                     UErrorCode& status) const;
572 
573 #endif  /* U_HIDE_INTERNAL_API */
574 
575     /**
576      * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own.
577      * @stable ICU 63
578      */
579     ~LocalizedNumberRangeFormatter();
580 
581   private:
582     std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {};
583 
584     const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const;
585 
586     explicit LocalizedNumberRangeFormatter(
587         const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other);
588 
589     explicit LocalizedNumberRangeFormatter(
590         NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>&& src) noexcept;
591 
592     LocalizedNumberRangeFormatter(const impl::RangeMacroProps &macros, const Locale &locale);
593 
594     LocalizedNumberRangeFormatter(impl::RangeMacroProps &&macros, const Locale &locale);
595 
596     // To give the fluent setters access to this class's constructor:
597     friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
598     friend class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>;
599 
600     // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor:
601     friend class UnlocalizedNumberRangeFormatter;
602 };
603 
604 /**
605  * The result of a number range formatting operation. This class allows the result to be exported in several data types,
606  * including a UnicodeString and a FieldPositionIterator.
607  *
608  * Instances of this class are immutable and thread-safe.
609  *
610  * @stable ICU 63
611  */
612 class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
613   public:
614     // Copybrief: this method is older than the parent method
615     /**
616      * @copybrief FormattedValue::toString()
617      *
618      * For more information, see FormattedValue::toString()
619      *
620      * @stable ICU 63
621      */
622     UnicodeString toString(UErrorCode& status) const override;
623 
624     // Copydoc: this method is new in ICU 64
625     /** @copydoc FormattedValue::toTempString() */
626     UnicodeString toTempString(UErrorCode& status) const override;
627 
628     // Copybrief: this method is older than the parent method
629     /**
630      * @copybrief FormattedValue::appendTo()
631      *
632      * For more information, see FormattedValue::appendTo()
633      *
634      * @stable ICU 63
635      */
636     Appendable &appendTo(Appendable &appendable, UErrorCode& status) const override;
637 
638     // Copydoc: this method is new in ICU 64
639     /** @copydoc FormattedValue::nextPosition() */
640     UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override;
641 
642     /**
643      * Extracts the formatted range as a pair of decimal numbers. This endpoint
644      * is useful for obtaining the exact number being printed after scaling
645      * and rounding have been applied by the number range formatting pipeline.
646      *
647      * The syntax of the unformatted numbers is a "numeric string"
648      * as defined in the Decimal Arithmetic Specification, available at
649      * http://speleotrove.com/decimal
650      *
651      * Example C++17 call site:
652      *
653      *     auto [ first, second ] = range.getDecimalNumbers<std::string>(status);
654      *
655      * @tparam StringClass A string class compatible with StringByteSink;
656      *         for example, std::string.
657      * @param status Set if an error occurs.
658      * @return A pair of StringClasses containing the numeric strings.
659      * @stable ICU 68
660      */
661     template<typename StringClass>
662     inline std::pair<StringClass, StringClass> getDecimalNumbers(UErrorCode& status) const;
663 
664     /**
665      * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was
666      * used. For example, if the first and second number were the same either before or after rounding occurred, an
667      * identity fallback was used.
668      *
669      * @return An indication the resulting identity situation in the formatted number range.
670      * @stable ICU 63
671      * @see UNumberRangeIdentityFallback
672      */
673     UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const;
674 
675     /**
676      * Default constructor; makes an empty FormattedNumberRange.
677      * @stable ICU 70
678      */
679     FormattedNumberRange()
680         : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {}
681 
682     /**
683      * Copying not supported; use move constructor instead.
684      */
685     FormattedNumberRange(const FormattedNumberRange&) = delete;
686 
687     /**
688      * Copying not supported; use move assignment instead.
689      */
690     FormattedNumberRange& operator=(const FormattedNumberRange&) = delete;
691 
692     /**
693      * Move constructor:
694      * Leaves the source FormattedNumberRange in an undefined state.
695      * @stable ICU 63
696      */
697     FormattedNumberRange(FormattedNumberRange&& src) noexcept;
698 
699     /**
700      * Move assignment:
701      * Leaves the source FormattedNumberRange in an undefined state.
702      * @stable ICU 63
703      */
704     FormattedNumberRange& operator=(FormattedNumberRange&& src) noexcept;
705 
706     /**
707      * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own.
708      * @stable ICU 63
709      */
710     ~FormattedNumberRange();
711 
712   private:
713     // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared
714     const impl::UFormattedNumberRangeData *fData;
715 
716     // Error code for the terminal methods
717     UErrorCode fErrorCode;
718 
719     /**
720      * Internal constructor from data type. Adopts the data pointer.
721      */
722     explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results)
723         : fData(results), fErrorCode(U_ZERO_ERROR) {}
724 
725     explicit FormattedNumberRange(UErrorCode errorCode)
726         : fData(nullptr), fErrorCode(errorCode) {}
727 
728     void getDecimalNumbers(ByteSink& sink1, ByteSink& sink2, UErrorCode& status) const;
729 
730     const impl::UFormattedNumberRangeData* getData(UErrorCode& status) const;
731 
732     // To allow PluralRules to access the underlying data
733     friend class ::icu::PluralRules;
734 
735     // To give LocalizedNumberRangeFormatter format methods access to this class's constructor:
736     friend class LocalizedNumberRangeFormatter;
737 
738     // To give C API access to internals
739     friend struct impl::UFormattedNumberRangeImpl;
740 };
741 
742 // inline impl of @stable ICU 68 method
743 template<typename StringClass>
744 std::pair<StringClass, StringClass> FormattedNumberRange::getDecimalNumbers(UErrorCode& status) const {
745     StringClass str1;
746     StringClass str2;
747     StringByteSink<StringClass> sink1(&str1);
748     StringByteSink<StringClass> sink2(&str2);
749     getDecimalNumbers(sink1, sink2, status);
750     return std::make_pair(str1, str2);
751 }
752 
753 /**
754  * See the main description in numberrangeformatter.h for documentation and examples.
755  *
756  * @stable ICU 63
757  */
758 class U_I18N_API NumberRangeFormatter final {
759   public:
760     /**
761      * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is not currently
762      * known at the call site.
763      *
764      * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining.
765      * @stable ICU 63
766      */
767     static UnlocalizedNumberRangeFormatter with();
768 
769     /**
770      * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is known at the call
771      * site.
772      *
773      * @param locale
774      *            The locale from which to load formats and symbols for number range formatting.
775      * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining.
776      * @stable ICU 63
777      */
778     static LocalizedNumberRangeFormatter withLocale(const Locale &locale);
779 
780     /**
781      * Use factory methods instead of the constructor to create a NumberFormatter.
782      */
783     NumberRangeFormatter() = delete;
784 };
785 
786 }  // namespace number
787 U_NAMESPACE_END
788 
789 #endif /* #if !UCONFIG_NO_FORMATTING */
790 
791 #endif /* U_SHOW_CPLUSPLUS_API */
792 
793 #endif // __NUMBERRANGEFORMATTER_H__
794 
795