11.3.1.2 qualifier_set

The qualifier_set type represents the set of all qualifiers together.

The qualifier_set type is equality-comparable, and can be dumped to standard error.

Method on qualifier_set: void debug () const

Dump the contents of this to standard error, for instance, the qualifier set containing const, _Atomic, and address space 3 would print as {const, _Atomic, AS3}.

A default-constructed qualifier set corresponds to the “default” qualification in C, i.e. the syntactically empty qualifier set. This qualifier set includes only the generic address space qualifier.

You can check for such a qualifier set:

Method on qualifier_set: bool nonempty_p () const
Method on qualifier_set: operator bool () const

true iff this is syntactically nonempty, i.e. if it contains any qualifier other than the generic address space qualifier.

A qualifier_set is, in fact, an aggregate of the two components named above. As such, it is possible to construct a qualifier_set from one or both of the above, and break it back down into its constituent parts.

Method on qualifier_set: pair<cv_qualifier, addr_space_t> split () const

This function breaks a qualifier_set into its constituent parts. It is intended to be used in combination with std::tie:

qualifier_set qs = given;
cv_qualifier cv;
addr_space_t as;
std::tie (cv, as) = qs.split ();

Usually, if you need to process the constituent parts of a qualifier set separately, this is what you want. By doing something like the above, if a new component is added to qualifier_sets, all places that need to process all the components become compile errors, and thus handling new qualifiers can be guided by the compiler.

It is also possible to access the individual components of a qualifier set:

Method on qualifier_set: cv_qualifier cv_quals () const
Method on qualifier_set: addr_space_t addr_space () const

Returns the respective component of this qualifier_set.

Most of the time, if you need one of the components, you need both. Consider using split (described above), so that adding a new component to a qualifier set raises a build error.

qualifier_set themselves form a partially-ordered set, with superset_of representing their ordering relation.

Method on qualifier_set: bool superset_of (qualifier_set other, bool pointee = false) const

Returns true if qualifiers in other can be replaced with qualifiers in this safely.

If not pointee, such a replacement is safe iff cv2 int * can be converted into cv1 int * where cv1 are the qualifiers in this and cv2 the qualifiers in other.

Otherwise, such a replacement is safe iff cv2 int * const * can be converted into cv1 int * const * where cv1 are the qualifiers in this and cv2 the qualifiers in other.

To add, remove, query the presence of or change the elements of qualifier sets, the following functions are available:

Method on qualifier_set: bool has (cv_qualifier other_cv)

true iff any qualifier in other_cv is part of this, i.e. if their intersection is nonempty.

Method on qualifier_set: void add (cv_qualifier qual)
Method on qualifier_set: qualifier_set with (cv_qualifier qual) const

Add qual to the current qualifier set, if not already present.

The former variant mutates an existing qualifier set, and the latter returns a new qualifier set.

These operations can also be invoked via the assignment and non-assignment bit-OR operators, respectively.

Method on qualifier_set: void remove (cv_qualifier qual)
Method on qualifier_set: qualifier_set without (cv_qualifier qual) const

Remove qual to the current qualifier set, if present.

The former variant mutates an existing qualifier set, and the latter returns a new qualifier set.

Method on qualifier_set: void set_as (addr_space_t as)
Method on qualifier_set: qualifier_set with_as (addr_space_t as) const

Replace address space qualifier in this with as.

The former variant mutates an existing qualifier set, and the latter returns a new qualifier set.

Method on qualifier_set: cv_qualifier intersect (cv_qualifier qual) const

Returns the cv_qualifiers present in both this and qual.

Method on qualifier_set: cv_qualifier symmetric_difference (cv_qualifier qual) const

Returns the symmetric difference of this and qual.

As the latter lacks an address space qualifier, the address space qualifier of this is kept.

This operation can also be invoked via the assignment and non-assignment bit-XOR operators.

qualifier_set provides fewer operations than cv_qualifier. This is because not all set operations make sense on a qualifier_set.

For instance, there is not necessarily always a union of two qualifier_set values, and it does not make sense to ask for the intersection of two qualifier_set values, due to the address space qualifier.

Instead, qualifier_set provides two partial operations for the union of two qualifier sets, depending on situation:

Method on qualifier_set: expected<qualifier_set, merge_error> merge (qualifier_set other, bool strict_addr_space = false) const

Attempt to produce a qualifier_set that’s a merge of the qualifiers in this and in other. Such a qualifier set can be used instead of either this or other safely (i.e. it is compatible with both), though perhaps through a conversion.

This corresponds to trying to find a common type for two expressions, for instance to determine the type of a conditional expression.

Such a qualifier set may not exist. If so, an unexpected value is returned containing a reason why.

If strict_addr_space, address space differences are forbidden. This corresponds to the pointee case in superset_of.

You may consider writing a wrapper for this function for your front-end, which emits a diagnostic and performs error recovery.

Method on qualifier_set: expected<qualifier_set, join_error> join (qualifier_set other) const

Attempt to produce a qualifier_set that’s a syntactic join of the qualifiers in this and in other.

Such a qualifier set is gotten by syntactically concatenating the two qualifier sets, i.e. if other is syntactically:

{x_1, x_2, ..., x_n}

and this is syntactically:

{y_1, y_2, ..., y_m}

then the resulting qualifier set is:

{x_1, x_2, ..., x_n, y_1, y_2, ..., y_m}

This corresponds to adding extra qualifiers when using a type alias, as in:

typedef const int cint;
volatile cint x;

where the qualification of the type of x is the join of the qualifier set containing const (and the generic address space), and the qualifier set containing volatile (and the generic address space).

Such a qualifier set may not exist. If so, an unexpected value is returned containing a reason why.

You should consider writing a wrapper for this function for your front-end, which emits a diagnostic and performs error recovery.