6 #ifndef MESSAGEFORMAT_DATA_MODEL_H
7 #define MESSAGEFORMAT_DATA_MODEL_H
9 #if U_SHOW_CPLUSPLUS_API
11 #if !UCONFIG_NO_FORMATTING
16 #include "unicode/messageformat2_data_model_names.h"
18 #ifndef U_HIDE_DEPRECATED_API
37 static inline std::vector<T> toStdVector(
const T* arr, int32_t len) {
38 std::vector<T> result;
39 for (int32_t i = 0; i < len; i++) {
40 result.push_back(arr[i]);
45 #if defined(U_REAL_MSVC)
49 #pragma warning(disable: 4251)
55 class MessageFormatter;
60 namespace data_model {
86 int32_t numParts()
const;
97 const Literal& getPart(int32_t i)
const;
170 swap(r1.bogus, r2.bogus);
171 swap(r1.parts, r2.parts);
172 swap(r1.len, r2.len);
204 friend class Builder;
281 Literal(
const Literal& other) : thisIsQuoted(other.thisIsQuoted), contents(other.contents) {}
293 swap(l1.thisIsQuoted, l2.thisIsQuoted);
294 swap(l1.contents, l2.contents);
326 bool operator<(const
Literal& other) const;
342 bool operator==(const
Literal& other) const;
354 bool thisIsQuoted = false;
366 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
370 #if defined(U_REAL_MSVC)
383 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
384 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
385 struct U_I18N_API std::_Nontrivial_dummy_type;
386 template class U_I18N_API std::_Variant_storage_<false, icu::UnicodeString, icu::message2::data_model::Literal>;
388 template class U_I18N_API std::variant<icu::UnicodeString, icu::message2::data_model::Literal>;
389 template class U_I18N_API std::optional<std::variant<icu::UnicodeString, icu::message2::data_model::Literal>>;
390 template class U_I18N_API std::optional<icu::message2::data_model::Literal>;
397 namespace data_model {
423 UBool isVariable()
const;
432 UBool isLiteral()
const;
441 virtual UBool isNull()
const;
461 const Literal& asLiteral()
const;
489 explicit Operand(
const Literal& l) : contents(l) {}
502 swap(o1.contents, o2.contents);
526 std::optional<std::variant<
VariableName, Literal>> contents;
564 const Literal& asLiteral()
const;
571 Key(
const Key& other) : contents(other.contents) {}
579 Key() : contents(std::nullopt) {}
589 explicit Key(
const Literal& lit) : contents(lit) {}
601 swap(k1.contents, k2.contents);
609 Key& operator=(
Key) noexcept;
623 bool operator<(const
Key& other) const;
637 bool operator==(const
Key& other) const;
646 std::optional<Literal> contents;
657 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
664 namespace data_model {
688 return toStdVector<Key>(keys.getAlias(), len);
716 Builder& add(Key&& key,
UErrorCode& status) noexcept;
747 Builder(
const Builder&) =
delete;
748 Builder& operator=(
const Builder&) =
delete;
749 Builder(Builder&&) =
delete;
750 Builder& operator=(Builder&&) =
delete;
786 swap(s1.len, s2.len);
787 swap(s1.keys, s2.keys);
811 friend class Builder;
812 friend class message2::Checker;
814 friend class message2::Serializer;
819 const Key* getKeysInternal()
const;
827 namespace data_model {
888 swap(o1.name, o2.name);
889 swap(o1.rand, o2.rand);
925 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
926 template class U_I18N_API LocalPointerBase<message2::data_model::Option>;
927 template class U_I18N_API LocalArray<message2::data_model::Option>;
932 namespace data_model {
939 int32_t size()
const;
941 const Option& getOption(int32_t,
UErrorCode&)
const;
942 friend inline void swap(OptionMap& m1, OptionMap& m2) noexcept {
945 swap(m1.bogus, m2.bogus);
946 swap(m1.options, m2.options);
947 swap(m1.len, m2.len);
949 OptionMap() : len(0) {}
950 OptionMap(
const OptionMap&);
951 OptionMap& operator=(OptionMap);
952 std::vector<Option> getOptions()
const {
953 return toStdVector<Option>(options.getAlias(), len);
956 OptionMap(Option*, int32_t);
957 virtual ~OptionMap();
962 bool checkDuplicates =
true;
969 friend inline void swap(Builder& m1, Builder& m2) noexcept {
972 swap(m1.options, m2.options);
973 swap(m1.checkDuplicates, m2.checkDuplicates);
976 Builder(
const Builder&) =
delete;
977 Builder& operator=(Builder) noexcept;
981 friend class message2::Serializer;
984 LocalArray<Option> options;
993 friend inline void swap(Callable& c1, Callable& c2) noexcept {
996 swap(c1.name, c2.name);
997 swap(c1.options, c2.options);
999 const FunctionName& getName()
const {
return name; }
1000 const OptionMap& getOptions()
const {
return options; }
1001 Callable(
const FunctionName& f,
const OptionMap& opts) : name(f), options(opts) {}
1002 Callable& operator=(Callable) noexcept;
1003 Callable(const Callable&);
1004 Callable() = default;
1005 virtual ~Callable();
1022 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1023 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
1024 template class U_I18N_API std::_Variant_storage_<false, icu::message2::data_model::Reserved,icu::message2::data_model::Callable>;
1026 template class U_I18N_API std::variant<icu::message2::data_model::Reserved,icu::message2::data_model::Callable>;
1032 namespace message2 {
1033 namespace data_model {
1079 const Reserved& asReserved()
const;
1090 const Callable* f = std::get_if<Callable>(&contents);
1092 if (f ==
nullptr) {
return {}; }
1093 const OptionMap& opts = f->getOptions();
1094 return opts.getOptions();
1108 bool isReservedSequence =
false;
1109 bool hasFunctionName =
false;
1110 bool hasOptions =
false;
1113 OptionMap::Builder options;
1127 Builder& setReserved(
Reserved&& reserved);
1189 Builder(
const Builder&) =
delete;
1190 Builder& operator=(
const Builder&) =
delete;
1191 Builder(Builder&&) =
delete;
1192 Builder& operator=(Builder&&) =
delete;
1212 swap(o1.contents, o2.contents);
1238 friend class Builder;
1239 friend class message2::Checker;
1241 friend class message2::Serializer;
1248 const OptionMap& getOptionsInternal()
const;
1250 std::variant<Reserved, Callable> contents;
1263 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1264 template class U_I18N_API std::optional<icu::message2::data_model::Operator>;
1265 template class U_I18N_API std::optional<icu::message2::data_model::Reserved>;
1271 namespace message2 {
1272 namespace data_model {
1274 typedef enum UMarkupType {
1337 std::vector<Option>
getOptions()
const {
return options.getOptions(); }
1376 OptionMap::Builder options;
1377 OptionMap::Builder attributes;
1378 UMarkupType type = UMARKUP_COUNT;
1398 Builder&
setOpen() { type = UMARKUP_OPEN;
return *
this; }
1407 Builder&
setClose() { type = UMARKUP_CLOSE;
return *
this; }
1476 Builder(
const Builder&) =
delete;
1477 Builder& operator=(
const Builder&) =
delete;
1478 Builder(Builder&&) =
delete;
1479 Builder& operator=(Builder&&) =
delete;
1483 friend class Builder;
1484 friend class message2::Serializer;
1489 OptionMap attributes;
1490 const OptionMap& getOptionsInternal()
const {
return options; }
1491 const OptionMap& getAttributesInternal()
const {
return attributes; }
1492 Markup(UMarkupType,
UnicodeString, OptionMap&&, OptionMap&&);
1520 UBool isStandaloneAnnotation()
const;
1532 UBool isFunctionCall()
const;
1543 UBool isReserved()
const;
1567 const Operand& getOperand()
const;
1590 bool hasOperand =
false;
1591 bool hasOperator =
false;
1594 OptionMap::Builder attributes;
1605 Builder& setOperand(Operand&& rAnd);
1615 Builder& setOperator(
Operator&& rAtor);
1663 Builder(
const Builder&) =
delete;
1664 Builder& operator=(
const Builder&) =
delete;
1665 Builder(Builder&&) =
delete;
1666 Builder& operator=(Builder&&) =
delete;
1679 swap(e1.rator, e2.rator);
1680 swap(e1.rand, e2.rand);
1681 swap(e1.attributes, e2.attributes);
1713 friend class message2::Serializer;
1729 Expression(const
Operator &rAtor, const Operand &rAnd, const OptionMap& attrs) : rator(rAtor), rand(rAnd), attributes(attrs) {}
1730 Expression(
const Operand &rAnd,
const OptionMap& attrs) : rator(std::nullopt), rand(Operand(rAnd)), attributes(attrs) {}
1731 Expression(
const Operator &rAtor,
const OptionMap& attrs) : rator(rAtor), rand(), attributes(attrs) {}
1732 std::optional<Operator> rator;
1734 OptionMap attributes;
1735 const OptionMap& getAttributesInternal()
const {
return attributes; }
1746 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1747 template class U_I18N_API LocalPointerBase<message2::data_model::Expression>;
1748 template class U_I18N_API LocalArray<message2::data_model::Expression>;
1752 namespace message2 {
1753 namespace data_model {
1799 if (expressionsLen <= 0 || !expressions.isValid()) {
1803 return toStdVector<Expression>(expressions.getAlias(), expressionsLen);
1817 friend class message2::Parser;
1820 std::optional<Reserved> body;
1821 UVector* expressions;
1889 Builder(
const Builder&) =
delete;
1890 Builder& operator=(
const Builder&) =
delete;
1891 Builder(Builder&&) =
delete;
1892 Builder& operator=(Builder&&) =
delete;
1905 swap(s1.keyword, s2.keyword);
1906 swap(s1.body, s2.body);
1907 swap(s1.expressions, s2.expressions);
1908 swap(s1.expressionsLen, s2.expressionsLen);
1940 friend class message2::Serializer;
1943 std::optional<Reserved> body;
1945 int32_t expressionsLen = 0;
1975 UBool isText()
const {
return std::holds_alternative<UnicodeString>(piece); }
2013 const Markup& asMarkup()
const;
2035 swap(p1.piece, p2.piece);
2099 std::variant<UnicodeString, Expression, Markup> piece;
2110 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2111 template class U_I18N_API LocalPointerBase<message2::data_model::PatternPart>;
2112 template class U_I18N_API LocalArray<message2::data_model::PatternPart>;
2113 template class U_I18N_API LocalPointerBase<message2::data_model::UnsupportedStatement>;
2114 template class U_I18N_API LocalArray<message2::data_model::UnsupportedStatement>;
2118 namespace message2 {
2119 namespace data_model {
2239 Builder(
const Builder&) =
delete;
2240 Builder& operator=(
const Builder&) =
delete;
2241 Builder(Builder&&) =
delete;
2242 Builder& operator=(Builder&&) =
delete;
2264 swap(p1.bogus, p2.bogus);
2265 swap(p1.len, p2.len);
2266 swap(p1.parts, p2.parts);
2301 using iterator_category = std::forward_iterator_tag;
2302 using difference_type = std::ptrdiff_t;
2303 using value_type = std::variant<UnicodeString, Expression, Markup>;
2304 using pointer = value_type*;
2305 using reference =
const value_type&;
2307 friend class Pattern;
2308 Iterator(
const Pattern* p, int32_t i) : pos(i), pat(p) {}
2309 friend bool operator== (
const Iterator& a,
const Iterator& b) {
return (a.pat == b.pat && a.pos == b.pos); }
2323 return patternContents(part);
2338 friend bool operator!= (
const Iterator& a,
const Iterator& b) {
return !(a == b); }
2342 friend class Builder;
2344 friend class message2::Serializer;
2367 int32_t numParts()
const;
2382 static const std::variant<UnicodeString, Expression, Markup>&
2383 patternContents(
const PatternPart& p) {
return p.piece; }
2477 namespace data_model {
2540 Binding(
const VariableName& v,
Expression&& e) : var(v), expr(std::move(e)), local(true), annotation(nullptr) {}
2552 swap(b1.var, b2.var);
2553 swap(b1.expr, b2.expr);
2554 swap(b1.local, b2.local);
2555 b1.updateAnnotation();
2556 b2.updateAnnotation();
2588 friend class message2::Checker;
2590 friend class message2::Parser;
2591 friend class message2::Serializer;
2602 const Callable* annotation =
nullptr;
2604 const OptionMap& getOptionsInternal()
const;
2606 bool hasAnnotation()
const {
return !local && (annotation !=
nullptr); }
2607 void updateAnnotation();
2618 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2619 template class U_I18N_API LocalPointerBase<message2::data_model::Variant>;
2620 template class U_I18N_API LocalPointerBase<message2::data_model::Binding>;
2621 template class U_I18N_API LocalArray<message2::data_model::Variant>;
2622 template class U_I18N_API LocalArray<message2::data_model::Binding>;
2626 namespace message2 {
2627 using namespace data_model;
2634 #ifndef U_IN_DOXYGEN
2635 class Matcher :
public UObject {
2637 Matcher& operator=(Matcher);
2638 Matcher(
const Matcher&);
2647 friend inline void swap(Matcher& m1, Matcher& m2) noexcept {
2658 swap(m1.selectors, m2.selectors);
2659 swap(m1.numSelectors, m2.numSelectors);
2660 swap(m1.variants, m2.variants);
2661 swap(m1.numVariants, m2.numVariants);
2666 friend class MFDataModel;
2668 Matcher(Expression* ss, int32_t ns, Variant* vs, int32_t nv);
2677 LocalArray<Expression> selectors;
2679 int32_t numSelectors = 0;
2681 LocalArray<Variant> variants;
2683 int32_t numVariants = 0;
2696 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2697 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
2698 template class U_I18N_API std::_Variant_storage_<false, icu::message2::Matcher,icu::message2::data_model::Pattern>;
2700 template class U_I18N_API std::variant<icu::message2::Matcher,icu::message2::data_model::Pattern>;
2706 namespace message2 {
2771 std::vector<Binding> result;
2773 return toStdVector<Binding>(bindings.getAlias(), bindingsLen);
2786 if (std::holds_alternative<Pattern>(body)) {
2789 const Matcher* match = std::get_if<Matcher>(&body);
2791 return toStdVector<Expression>(match->selectors.getAlias(), match->numSelectors);
2803 if (std::holds_alternative<Pattern>(body)) {
2806 const Matcher* match = std::get_if<Matcher>(&body);
2808 return toStdVector<Variant>(match->variants.getAlias(), match->numVariants);
2820 std::vector<UnsupportedStatement> result;
2822 return toStdVector<UnsupportedStatement>(unsupportedStatements.getAlias(), unsupportedStatementsLen);
2835 const Pattern& getPattern()
const;
2873 swap(m1.body, m2.body);
2874 swap(m1.bindings, m2.bindings);
2875 swap(m1.bindingsLen, m2.bindingsLen);
2876 swap(m1.unsupportedStatements, m2.unsupportedStatements);
2877 swap(m1.unsupportedStatementsLen, m2.unsupportedStatementsLen);
2910 friend class MFDataModel;
2912 void checkDuplicate(
const VariableName&,
UErrorCode&)
const;
2914 bool hasPattern =
true;
2915 bool hasSelectors =
false;
2918 UVector* selectors =
nullptr;
2919 UVector* variants =
nullptr;
2920 UVector* bindings =
nullptr;
2921 UVector* unsupportedStatements =
nullptr;
2983 Builder& setPattern(
Pattern&& pattern);
3003 MFDataModel build(
UErrorCode& status)
const noexcept;
3024 Builder(
const Builder&) =
delete;
3025 Builder& operator=(
const Builder&) =
delete;
3026 Builder(Builder&&) =
delete;
3027 Builder& operator=(Builder&&) =
delete;
3031 friend class Checker;
3033 friend class Serializer;
3037 bool hasPattern()
const {
return std::holds_alternative<Pattern>(body); }
3043 std::variant<Matcher, Pattern> body;
3047 int32_t bindingsLen = 0;
3053 int32_t unsupportedStatementsLen = 0;
3055 const Binding* getLocalVariablesInternal()
const;
3056 const Expression* getSelectorsInternal()
const;
3057 const Variant* getVariantsInternal()
const;
3060 int32_t numSelectors()
const {
3061 const Matcher* matcher = std::get_if<Matcher>(&body);
3062 return (matcher ==
nullptr ? 0 : matcher->numSelectors);
3064 int32_t numVariants()
const {
3065 const Matcher* matcher = std::get_if<Matcher>(&body);
3066 return (matcher ==
nullptr ? 0 : matcher->numVariants);
3070 void initBindings(
const Binding*);
3072 MFDataModel(
const Builder& builder,
UErrorCode&) noexcept;
3079 #endif // U_HIDE_DEPRECATED_API
3087 #endif // MESSAGEFORMAT_DATA_MODEL_H
friend void swap(SelectorKeys &s1, SelectorKeys &s2) noexcept
Non-member swap function.
UBool isMarkup() const
Checks if the part is a markup part.
A Variant pairs a list of keys with a pattern It corresponds to the Variant interface defined in http...
A PatternPart is a single element (text or expression) in a Pattern.
UBool isExpression() const
Checks if the part is an expression part.
friend void swap(Variant &v1, Variant &v2) noexcept
Non-member swap function.
bool operator!=(const StringPiece &x, const StringPiece &y)
Global operator != for StringPiece.
Builder & setClose()
Sets this to be an closing markup.
Variant(const SelectorKeys &keys, Pattern &&pattern)
Constructor.
const VariableName & getVariable() const
Accesses the left-hand side of the binding.
friend void swap(Reserved &r1, Reserved &r2) noexcept
Non-member swap function.
Builder & setName(const UnicodeString &n)
Sets the name of this markup.
UBool isWildcard() const
Determines if this is a wildcard key.
Literal(const Literal &other)
Copy constructor.
T * getAlias() const
Access without ownership change.
const std::vector< Expression > getSelectors() const
Accesses the selectors.
U_EXPORT UBool operator==(const StringPiece &x, const StringPiece &y)
Global operator == for StringPiece.
friend void swap(Operator &o1, Operator &o2) noexcept
Non-member swap function.
Literal(UBool q, const UnicodeString &s)
Literal constructor.
The UnsupportedStatement class corresponds to the reserved-statement nonterminal in the MessageFormat...
Option()
Default constructor.
UBool isOpen() const
Checks if this markup is an opening tag.
friend void swap(Literal &l1, Literal &l2) noexcept
Non-member swap function.
const Operand & getValue() const
Accesses the right-hand side of the option.
The mutable Reserved::Builder class allows the reserved sequence to be constructed one part at a time...
SelectorKeys()
Default constructor.
std::vector< Variant > getVariants() const
Accesses the variants.
std::vector< Binding > getLocalVariables() const
Accesses the local variable declarations for this data model.
Option(const UnicodeString &n, Operand &&r)
Constructor.
Markup()
Default constructor.
The Literal class corresponds to the literal nonterminal in the MessageFormat 2 grammar, https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf and the Literal interface defined in // https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions.
An Option pairs an option name with an Operand.
const UnicodeString & getName() const
Gets the name of this markup.
Iterator operator++()
Increment operator (advances to the next iterator position)
Key(const Literal &lit)
Literal key constructor.
#define U_I18N_API
Set to export library symbols from inside the i18n library, and to import them from outside...
Operand(const Literal &l)
Literal operand constructor.
The Pattern::Iterator class provides an iterator over the formattable parts of a pattern.
Operand()
Default constructor.
friend void swap(Expression &e1, Expression &e2) noexcept
Non-member swap function.
std::vector< Key > getKeys() const
Returns the underlying list of keys.
friend void swap(UnsupportedStatement &s1, UnsupportedStatement &s2) noexcept
Non-member swap function.
The Markup class corresponds to the markup nonterminal in the MessageFormat 2 grammar and the markup ...
"Smart pointer" base class; do not use directly: use LocalPointer etc.
Key(const Key &other)
Copy constructor.
C++ API: "Smart pointers" for use with and in ICU4C C++ code.
std::vector< UnsupportedStatement > getUnsupportedStatements() const
Accesses the unsupported statements for this data model.
The MFDataModel class describes a parsed representation of the text of a message. ...
UBool isClose() const
Checks if this markup is an closing tag.
friend void swap(Option &o1, Option &o2) noexcept
Non-member swap function.
friend void swap(Binding &b1, Binding &b2) noexcept
Non-member swap function.
UBool isQuoted() const
Determines if this literal appeared as a quoted literal in the message.
"Smart pointer" class, deletes objects via the C++ array delete[] operator.
const UnicodeString & getName() const
Accesses the left-hand side of the option.
const Pattern & getPattern() const
Accesses the pattern of the variant.
The Operator class corresponds to the FunctionRef | Reserved type in the Expression interface defined...
The Reserved class represents a reserved annotation, as in the reserved nonterminal in the MessageFor...
friend void swap(Key &k1, Key &k2) noexcept
Non-member swap function.
std::vector< Expression > getExpressions() const
Accesses the expressions of this statement.
friend void swap(MFDataModel &m1, MFDataModel &m2) noexcept
Non-member swap function.
PatternPart(Expression &&e)
Expression part constructor.
Iterator end() const
Returns a special value to mark the end of iteration.
Pattern()
Default constructor.
const SelectorKeys & getKeys() const
Accesses the keys of the variant.
PatternPart(Markup &&m)
Markup part constructor.
Key()
Wildcard constructor; constructs a Key representing the catchall or wildcard key, '*'...
The Operand class corresponds to the operand nonterminal in the MessageFormat 2 grammar, https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf .
Builder & setOpen()
Sets this to be an opening markup.
The Expression class corresponds to the expression nonterminal in the MessageFormat 2 grammar and the...
Binding(const VariableName &v, Expression &&e)
Constructor.
reference operator*() const
Dereference operator (gets the element at the current iterator position)
A Binding pairs a variable name with an expression.
UErrorCode
Standard ICU4C error code type, a substitute for exceptions.
The Key class corresponds to the key nonterminal in the MessageFormat 2 grammar, https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf .
Iterator begin() const
Returns the parts of this pattern.
std::vector< Option > getOptions() const
Accesses function options.
Operand(const UnicodeString &v)
Variable operand constructor.
Basic definitions for ICU, for both C and C++ APIs.
A Pattern is a sequence of formattable parts.
UnicodeString is a string class that stores Unicode characters directly and provides similar function...
const UnicodeString & getKeyword() const
Accesses the keyword of this statement.
std::vector< Option > getAttributes() const
Gets the attributes of this markup.
UBool isLocal() const
Returns true if and only if this binding represents a local declaration.
The SelectorKeys class represents the key list for a single variant.
std::vector< Option > getOptions() const
Gets the options of this markup.
friend void swap(PatternPart &p1, PatternPart &p2) noexcept
Non-member swap function.
UBool isStandalone() const
Checks if this markup is an standalone tag.
UObject is the common ICU "boilerplate" class.
std::vector< Option > getAttributes() const
Gets the attributes of this expression.
UMemory is the common ICU base class.
Builder & setStandalone()
Sets this to be a standalone markup.
friend void swap(Operand &o1, Operand &o2) noexcept
Non-member swap function.
UBool isText() const
Checks if the part is a text part.
int8_t UBool
The ICU boolean type, a signed-byte integer.
UBool isReserved() const
Determines if this operator is a reserved annotation.
friend void swap(Pattern &p1, Pattern &p2) noexcept
Non-member swap function.