| 1 | Operator Defaults
 | 
|---|
| 2 | =================
 | 
|---|
| 3 | 
 | 
|---|
| 4 | This proposal introduces a new syntax for requesting a default implementation
 | 
|---|
| 5 | of an operator and the rules for generating them.
 | 
|---|
| 6 | 
 | 
|---|
| 7 | This is to build on the implied relationships between operators. Most default
 | 
|---|
| 8 | operators will be implemented in terms of other operators. As a fall-back
 | 
|---|
| 9 | operators can try to figure out an intuitive definition from inspection of the
 | 
|---|
| 10 | type's sue declaration.
 | 
|---|
| 11 | 
 | 
|---|
| 12 | Syntax
 | 
|---|
| 13 | ------
 | 
|---|
| 14 | 
 | 
|---|
| 15 | The syntax for requesting a default implementation is part of function
 | 
|---|
| 16 | definition. After the function signature (after the parameter list) instead
 | 
|---|
| 17 | of putting the function body you declare it to be equal to default.
 | 
|---|
| 18 | 
 | 
|---|
| 19 |     box ?+?(box const & left, box const & right) = default;
 | 
|---|
| 20 | 
 | 
|---|
| 21 | These can exist along side any forward definitions of the function, but would
 | 
|---|
| 22 | conflict with any other complete definitions or deletions of the function.
 | 
|---|
| 23 | 
 | 
|---|
| 24 | It could be valid syntax on any function, but possibly all non-operators would
 | 
|---|
| 25 | report that no default implementation available.
 | 
|---|
| 26 | 
 | 
|---|
| 27 | If default implementations are really popular and we don't need additional
 | 
|---|
| 28 | information about the signature a more compact syntax could be added.
 | 
|---|
| 29 | 
 | 
|---|
| 30 |     default box( ?(), ?=?, ?!=?, ?<?, ?>?, ?<=?, ?>=? );
 | 
|---|
| 31 | 
 | 
|---|
| 32 | Generation Strategies
 | 
|---|
| 33 | ---------------------
 | 
|---|
| 34 | 
 | 
|---|
| 35 | There exists a system around the default generation that selects how to
 | 
|---|
| 36 | generate a given function if one can be generated at all. This section
 | 
|---|
| 37 | describes that system and some of the logic behind it.
 | 
|---|
| 38 | 
 | 
|---|
| 39 | There are two main strategies for generating an operator implementation.
 | 
|---|
| 40 | 
 | 
|---|
| 41 | The first is to mimic the relationship between operators on the primitive
 | 
|---|
| 42 | types by defining a new operator in terms of an existing operator on the same
 | 
|---|
| 43 | type. For instance `++i` is equivalent to `i += 1`, so the generated
 | 
|---|
| 44 | implementation will "look like" that.
 | 
|---|
| 45 | 
 | 
|---|
| 46 | The second is to inspect the structure of the declaration to guess at what
 | 
|---|
| 47 | the default implementation would be. Because of that it is dependent on the
 | 
|---|
| 48 | kind of declaration, a structure doesn't have the same rules as an
 | 
|---|
| 49 | enumeration. Also it is similar to the implicate definitions currently created
 | 
|---|
| 50 | by the compiler and the generation methods for many are carried over.
 | 
|---|
| 51 | 
 | 
|---|
| 52 | From these strategies a method of generation (a particular set of rules that
 | 
|---|
| 53 | define an implementation from the type and existing functions) has to be
 | 
|---|
| 54 | picked, but often there is more than on reasonable choice. In these cases they
 | 
|---|
| 55 | are ordered and the first (best) one whose requirements is met is then used.
 | 
|---|
| 56 | See "Circular Requirements" below for some exceptions and extensions to this
 | 
|---|
| 57 | pattern.
 | 
|---|
| 58 | 
 | 
|---|
| 59 | Generally the methods based on operators come first as they propagate any
 | 
|---|
| 60 | unusual implementations from the explicate operators to the ones being
 | 
|---|
| 61 | generated. If all of those fail then the intuitive definition based on the
 | 
|---|
| 62 | declaration's shape is used. The general patterns in this area for the
 | 
|---|
| 63 | different sue types follow.
 | 
|---|
| 64 | 
 | 
|---|
| 65 | ### Structures
 | 
|---|
| 66 | Structures will usually apply the operation to each field, or when there are
 | 
|---|
| 67 | two parameters the matching pairs of fields from each, and then combine the
 | 
|---|
| 68 | results.
 | 
|---|
| 69 | 
 | 
|---|
| 70 | This does require that the fields have certain operators defined on them.
 | 
|---|
| 71 | In this respect it is still operator based generation, but we use inspection
 | 
|---|
| 72 | on the structure to find out which operators to use.
 | 
|---|
| 73 | 
 | 
|---|
| 74 | Also, for the purposes of default generation types declared with the
 | 
|---|
| 75 | concurrency modifiers (coroutine, monitor and thread) are considered structs.
 | 
|---|
| 76 | The default implementations should be the same as if you had written out the
 | 
|---|
| 77 | extra field and functions by hand.
 | 
|---|
| 78 | 
 | 
|---|
| 79 | ### Enumerations
 | 
|---|
| 80 | The two ways of using enumerations are considered. First as "one of" the
 | 
|---|
| 81 | list options as in normal use, the second is as a set of flags where each
 | 
|---|
| 82 | option represents a flag that may or may not be set.
 | 
|---|
| 83 | 
 | 
|---|
| 84 | Currently there is no way to specify which nor does the system attempt to
 | 
|---|
| 85 | guess by checking assigned values. There is one case where an operator could
 | 
|---|
| 86 | have a meaningful default in both versions. If both are included then we can
 | 
|---|
| 87 | try to pick one by scanning the enumeration to see what values its options
 | 
|---|
| 88 | are given (a linear series or powers of 2) could be used. In all other cases
 | 
|---|
| 89 | the definition that makes sense can be assumed.
 | 
|---|
| 90 | 
 | 
|---|
| 91 | ### Unions
 | 
|---|
| 92 | Unions are the hardest to deal with because the instance does not show which
 | 
|---|
| 93 | field in the union is being used. Because of that there are very few intuitive
 | 
|---|
| 94 | definitions to use and the ones that do depend on bit-wise operations and only
 | 
|---|
| 95 | if the union is made of primitive types.
 | 
|---|
| 96 | 
 | 
|---|
| 97 | ### Traits
 | 
|---|
| 98 | Default operations are not supported on traits. A function implemented by the
 | 
|---|
| 99 | default generation may be used to satisfy an assertion. However a default
 | 
|---|
| 100 | implementation may not be requested on a polymorphic function.
 | 
|---|
| 101 | 
 | 
|---|
| 102 | It could in theory, limiting to operation based generation and using the
 | 
|---|
| 103 | operations available in the assertion list. There are a few problems:
 | 
|---|
| 104 | +   Knowing the entire set of functions being generated is very useful in some
 | 
|---|
| 105 |     cases and this information is quickly lost with polymorphic functions.
 | 
|---|
| 106 | +   The rules for choosing a generation method do not match how a polymorphic
 | 
|---|
| 107 |     function is selected so the results can be inconsistent.
 | 
|---|
| 108 | +   It is easily to mimic with a polymorphic function already, writing out one
 | 
|---|
| 109 |     generic function and including it.
 | 
|---|
| 110 | 
 | 
|---|
| 111 | Default Generation
 | 
|---|
| 112 | ------------------
 | 
|---|
| 113 | 
 | 
|---|
| 114 | Here are the generation methods. Unless otherwise stated they are listed in
 | 
|---|
| 115 | priority order. That is the first one mentioned that a type fits (has all the
 | 
|---|
| 116 | required operators or its form matches) will be used.
 | 
|---|
| 117 | 
 | 
|---|
| 118 | The operator based constructions can be used on any sue type, those that
 | 
|---|
| 119 | require a particular kind mention that.
 | 
|---|
| 120 | 
 | 
|---|
| 121 | ### Constructor: ?{}
 | 
|---|
| 122 | Note that requesting any constructor to be generated counts as defining a
 | 
|---|
| 123 | constructor for purposes of disabling the implicate constructors. There are
 | 
|---|
| 124 | no operator based methods for generating constructors.
 | 
|---|
| 125 | 
 | 
|---|
| 126 | For structures: For the zero argument constructor (aka the default constructor,
 | 
|---|
| 127 | which takes just a reference to the value to construct) each field is
 | 
|---|
| 128 | constructed with its zero argument constructor. For the copy constructor each
 | 
|---|
| 129 | field is copy constructed from the same field in the copied structure. For
 | 
|---|
| 130 | zero_t and one_t each field is also constructed from zero_t or one_t.
 | 
|---|
| 131 | 
 | 
|---|
| 132 | For enumerations: For the zero argument constructor the value is set to 0 if
 | 
|---|
| 133 | one of the enumeration options is 0 (or set to the first value in the enum).
 | 
|---|
| 134 | For the zero_t constructor it is the same except the check is skipped (and no
 | 
|---|
| 135 | or). The copy constructor is the same as memcpy.
 | 
|---|
| 136 | 
 | 
|---|
| 137 | For unions: For the zero argument constructor of a union that is constructed
 | 
|---|
| 138 | entirely of primitive types (or other types that zero argument construct to
 | 
|---|
| 139 | all 0s) the union filled with 0s. For the copy constructor of a union of types
 | 
|---|
| 140 | that all have trivial copy constructors memcpy is used.
 | 
|---|
| 141 | 
 | 
|---|
| 142 | ### Destructor: ^?{}
 | 
|---|
| 143 | Requesting the default destructor should be the same as having it implicitly
 | 
|---|
| 144 | defined. Destructors only have one signature and the intuitive definition for
 | 
|---|
| 145 | that is the same as without the signature.
 | 
|---|
| 146 | 
 | 
|---|
| 147 | Still it should be allowed for consistency. It also allows it to be forward
 | 
|---|
| 148 | declared and then generated in a .cfa file.
 | 
|---|
| 149 | 
 | 
|---|
| 150 | ### Assignment: ?=?
 | 
|---|
| 151 | Default assignment is only supported between two objects of the same type.
 | 
|---|
| 152 | For structures it is field to field assignment. For enumerations and unions
 | 
|---|
| 153 | of primitives or trivially copiable types it the same as memcpy.
 | 
|---|
| 154 | 
 | 
|---|
| 155 | ### Equality: ?==? ?!=?
 | 
|---|
| 156 | Both equality operations can be implemented by negating the result of the
 | 
|---|
| 157 | other operations.
 | 
|---|
| 158 | 
 | 
|---|
| 159 | For structures: Equality can be implement by checking equality on each pair of
 | 
|---|
| 160 | matching fields and taking the logical and of the results. Inequality can be
 | 
|---|
| 161 | implemented by checking inequality on each pair of matching fields and taking
 | 
|---|
| 162 | the logical or of the results.
 | 
|---|
| 163 | 
 | 
|---|
| 164 | Both logical operations could be short circuiting. Without side effects it is
 | 
|---|
| 165 | purely an optimization.
 | 
|---|
| 166 | 
 | 
|---|
| 167 | For enumerations: Both operations are the same as on the underlying integral.
 | 
|---|
| 168 | 
 | 
|---|
| 169 | For unions: If it is assumed that the different branches represent different
 | 
|---|
| 170 | views of the same data and this data is primitive, than bit-wise comparisons
 | 
|---|
| 171 | can be used.
 | 
|---|
| 172 | 
 | 
|---|
| 173 | ### Comparison: ?<? ?>? ?<=? ?>=?
 | 
|---|
| 174 | Less than can be implemented by flipping the arguments on greater than.
 | 
|---|
| 175 | Greater than can be implemented by flipping less then. Less than or equal to
 | 
|---|
| 176 | can be implemented by flipping greater than or equal to. Greater than or equal
 | 
|---|
| 177 | to can be implemented by flipping less than or equal to.
 | 
|---|
| 178 | 
 | 
|---|
| 179 | Less than or equal to can be implemented by using less than, equals and taking
 | 
|---|
| 180 | the or of the results. Greater than or equal to can be implemented by using
 | 
|---|
| 181 | greater than, equals and taking the or of the results.
 | 
|---|
| 182 | 
 | 
|---|
| 183 | > The trick of negating comparisons is not used. As an example ?<? is not
 | 
|---|
| 184 | > (boolean) not ?>=? unless the type is strictly ordered. For operator based
 | 
|---|
| 185 | > overloads that might not be true in very reasonable implementations so it is
 | 
|---|
| 186 | > not assumed.
 | 
|---|
| 187 | 
 | 
|---|
| 188 | Opposite less than can be implemented as less than or equal to and not equal
 | 
|---|
| 189 | to. Greater than can be implemented as greater than or equal to and not equal
 | 
|---|
| 190 | to.
 | 
|---|
| 191 | 
 | 
|---|
| 192 | For enumerations: Enumerations that represent one of all operations are the
 | 
|---|
| 193 | same as on the underlying integral. Enumerations that represent a set of
 | 
|---|
| 194 | options could replace less then with subset of and greator than with superset
 | 
|---|
| 195 | of and use bit-wise masking to implement those operations.
 | 
|---|
| 196 | 
 | 
|---|
| 197 | ### Binary & Relative Assignment Operators: ?_? ?_=?
 | 
|---|
| 198 | This applies to each operator in the form of `T ?_?(T, T);` for some type T
 | 
|---|
| 199 | and has a matching relative assignment operator `T& ?_=?(T&, T)` where the
 | 
|---|
| 200 | `_` in both is replaced by some string of operator characters.
 | 
|---|
| 201 | 
 | 
|---|
| 202 | The binary operator can be created by copying the left argument, using the
 | 
|---|
| 203 | relative assignment with the right argument and returning the updated copy.
 | 
|---|
| 204 | 
 | 
|---|
| 205 | The relative assignment operator can be implemented by using the binary
 | 
|---|
| 206 | operation to create a copy, then assigning the result to the left argument.
 | 
|---|
| 207 | The left argument should then be returned. For the signature above it would
 | 
|---|
| 208 | return by reference. The signature `T ?_=?(T&, T)` could also be supported in
 | 
|---|
| 209 | which case it would return by copy.
 | 
|---|
| 210 | 
 | 
|---|
| 211 | ### Minus: -? ?-?
 | 
|---|
| 212 | Unary minus can be implemented by subtracting argument from the value created
 | 
|---|
| 213 | from zero_t.
 | 
|---|
| 214 | 
 | 
|---|
| 215 | Binary minus can be implemented by negating (with unary minus) the right
 | 
|---|
| 216 | argument and adding the result to the left argument.
 | 
|---|
| 217 | 
 | 
|---|
| 218 | ### Increment & Decrement: ++? ?++ --? ?--
 | 
|---|
| 219 | Either pre- operation can implemented by applying the post- operation and then
 | 
|---|
| 220 | returning a reference to, or copy of, the updated value. Either post-
 | 
|---|
| 221 | operation can be implemented by copying the argument, applying the pre-
 | 
|---|
| 222 | operation to the original and returning the copy.
 | 
|---|
| 223 | 
 | 
|---|
| 224 | Pre-increment can be implemented by using addition assignment by the value
 | 
|---|
| 225 | constructed from one_t. Pre-decrement can be implemented by using subtraction
 | 
|---|
| 226 | assignment by the value from one_t.
 | 
|---|
| 227 | 
 | 
|---|
| 228 | Because many of the operations used have there own default implementations
 | 
|---|
| 229 | (for example: ?+=? from ?+? or field-wise one_t construction) this list could
 | 
|---|
| 230 | be expanded by replacing a function call with the default implementation for
 | 
|---|
| 231 | that function. This might work for the post- operations generated from
 | 
|---|
| 232 | relative assignment, the one_t constructed object and copying, but the logical
 | 
|---|
| 233 | connection becomes weaker and weaker as that process continues.
 | 
|---|
| 234 | 
 | 
|---|
| 235 | ### Bit Manipulation: ?|? ?&? ~? ?<<? ?>>?
 | 
|---|
| 236 | No operation based construction is provided for bit manipulation operators.
 | 
|---|
| 237 | 
 | 
|---|
| 238 | For enumerations that are considered sets of flags: And returns a set with all
 | 
|---|
| 239 | flags set in both operand sets, or returns a set with all flags set that are
 | 
|---|
| 240 | set in either operand sets and not returns a set with all flags set that are
 | 
|---|
| 241 | not set in the operand set.
 | 
|---|
| 242 | 
 | 
|---|
| 243 | > And it would be possible to actually implement this for any sized type and
 | 
|---|
| 244 | > just do the bitwise operation and trust the user that it makes sense if they
 | 
|---|
| 245 | > request it.
 | 
|---|
| 246 | 
 | 
|---|
| 247 | Also for set enumerations, the signature `T ?<<?(one_t, unsigned)` also has
 | 
|---|
| 248 | some use, as it can be used to implement a loop that goes over each flag,
 | 
|---|
| 249 | instead of each combination of flags.
 | 
|---|
| 250 | 
 | 
|---|
| 251 | ### Logical Negation: !?
 | 
|---|
| 252 | Not can be implemented by negating the result of a conversion to boolean, the
 | 
|---|
| 253 | does not equal 0 test.
 | 
|---|
| 254 | 
 | 
|---|
| 255 | Circular Requirements
 | 
|---|
| 256 | ---------------------
 | 
|---|
| 257 | 
 | 
|---|
| 258 | There are several cases where there are two operators that can be implemented
 | 
|---|
| 259 | with the other operator. If both are implemented that way calling either of
 | 
|---|
| 260 | them could result in infinite recursion.
 | 
|---|
| 261 | 
 | 
|---|
| 262 | The simplest way to handle the issue would be to tell the user to not do that,
 | 
|---|
| 263 | they are responsible for providing the base operations. This is C like but is
 | 
|---|
| 264 | perhaps more error prone than it would save in work and if we do check we can
 | 
|---|
| 265 | automatically use fallbacks.
 | 
|---|
| 266 | 
 | 
|---|
| 267 | Before generating any default implementations the compiler should generate
 | 
|---|
| 268 | a list of everything it has been requested and ignore any generation methods
 | 
|---|
| 269 | that would lead to chains instead of counting other defaults that could lead
 | 
|---|
| 270 | to a loop. As a further improvment this could be done selectively to break
 | 
|---|
| 271 | rings while allowing chains of non-recurive implementations.
 | 
|---|
| 272 | 
 | 
|---|
| 273 | For instance if both ?==? and ?!=? are requested they cannot both be defined
 | 
|---|
| 274 | as the negation of each other. In the simple version they would both be
 | 
|---|
| 275 | generated by introspection on the declaration. With the more selective version
 | 
|---|
| 276 | one could be generated by introspection and the other by negating that result.
 | 
|---|
| 277 | 
 | 
|---|
| 278 | However there are still ways to get around this by placing the function
 | 
|---|
| 279 | definitions in different translation units or defining a function that uses
 | 
|---|
| 280 | an operator that is default generated to use it. Searching for all these cases
 | 
|---|
| 281 | is probably not worth it, although checking for some might be useful warnings.
 | 
|---|