Operator Defaults
=================

This proposal introduces a new syntax for requesting a default implementation
of an operator and the rules for generating them.

This is to build on the implied relationships between operators. Most default
operators will be implemented in terms of other operators. As a fall-back
operators can try to figure out an intuitive definition from inspection of the
type's sue declaration.

Syntax
------

The syntax for requesting a default implementation is part of function
definition. After the function signature (after the parameter list) instead
of putting the function body you declare it to be equal to default.

    box ?+?(box const & left, box const & right) = default;

These can exist along side any forward definitions of the function, but would
conflict with any other complete definitions or deletions of the function.

It could be valid syntax on any function, but possibly all non-operators would
report that no default implementation available.

If default implementations are really popular and we don't need additional
information about the signature a more compact syntax could be added.

    default box( ?(), ?=?, ?!=?, ?<?, ?>?, ?<=?, ?>=? );

Generation Strategies
---------------------

There exists a system around the default generation that selects how to
generate a given function if one can be generated at all. This section
describes that system and some of the logic behind it.

There are two main strategies for generating an operator implementation.

The first is to mimic the relationship between operators on the primitive
types by defining a new operator in terms of an existing operator on the same
type. For instance `++i` is equivalent to `i += 1`, so the generated
implementation will "look like" that.

The second is to inspect the structure of the declaration to guess at what
the default implementation would be. Because of that it is dependent on the
kind of declaration, a structure doesn't have the same rules as an
enumeration. Also it is similar to the implicate definitions currently created
by the compiler and the generation methods for many are carried over.

From these strategies a method of generation (a particular set of rules that
define an implementation from the type and existing functions) has to be
picked, but often there is more than on reasonable choice. In these cases they
are ordered and the first (best) one whose requirements is met is then used.
See "Circular Requirements" below for some exceptions and extensions to this
pattern.

Generally the methods based on operators come first as they propagate any
unusual implementations from the explicate operators to the ones being
generated. If all of those fail then the intuitive definition based on the
declaration's shape is used. The general patterns in this area for the
different sue types follow.

### Structures
Structures will usually apply the operation to each field, or when there are
two parameters the matching pairs of fields from each, and then combine the
results.

This does require that the fields have certain operators defined on them.
In this respect it is still operator based generation, but we use inspection
on the structure to find out which operators to use.

Also, for the purposes of default generation types declared with the
concurrency modifiers (coroutine, monitor and thread) are considered structs.
The default implementations should be the same as if you had written out the
extra field and functions by hand.

### Enumerations
The two ways of using enumerations are considered. First as "one of" the
list options as in normal use, the second is as a set of flags where each
option represents a flag that may or may not be set.

Currently there is no way to specify which nor does the system attempt to
guess by checking assigned values. There is one case where an operator could
have a meaningful default in both versions. If both are included then we can
try to pick one by scanning the enumeration to see what values its options
are given (a linear series or powers of 2) could be used. In all other cases
the definition that makes sense can be assumed.

### Unions
Unions are the hardest to deal with because the instance does not show which
field in the union is being used. Because of that there are very few intuitive
definitions to use and the ones that do depend on bit-wise operations and only
if the union is made of primitive types.

### Traits
Default operations are not supported on traits. A function implemented by the
default generation may be used to satisfy an assertion. However a default
implementation may not be requested on a polymorphic function.

It could in theory, limiting to operation based generation and using the
operations available in the assertion list. There are a few problems:
+   Knowing the entire set of functions being generated is very useful in some
    cases and this information is quickly lost with polymorphic functions.
+   The rules for choosing a generation method do not match how a polymorphic
    function is selected so the results can be inconsistent.
+   It is easily to mimic with a polymorphic function already, writing out one
    generic function and including it.

Default Generation
------------------

Here are the generation methods. Unless otherwise stated they are listed in
priority order. That is the first one mentioned that a type fits (has all the
required operators or its form matches) will be used.

The operator based constructions can be used on any sue type, those that
require a particular kind mention that.

### Constructor: ?{}
Note that requesting any constructor to be generated counts as defining a
constructor for purposes of disabling the implicate constructors. There are
no operator based methods for generating constructors.

For structures: For the zero argument constructor (aka the default constructor,
which takes just a reference to the value to construct) each field is
constructed with its zero argument constructor. For the copy constructor each
field is copy constructed from the same field in the copied structure. For
zero_t and one_t each field is also constructed from zero_t or one_t.

For enumerations: For the zero argument constructor the value is set to 0 if
one of the enumeration options is 0 (or set to the first value in the enum).
For the zero_t constructor it is the same except the check is skipped (and no
or). The copy constructor is the same as memcpy.

For unions: For the zero argument constructor of a union that is constructed
entirely of primitive types (or other types that zero argument construct to
all 0s) the union filled with 0s. For the copy constructor of a union of types
that all have trivial copy constructors memcpy is used.

### Destructor: ^?{}
Requesting the default destructor should be the same as having it implicitly
defined. Destructors only have one signature and the intuitive definition for
that is the same as without the signature.

Still it should be allowed for consistency. It also allows it to be forward
declared and then generated in a .cfa file.

### Assignment: ?=?
Default assignment is only supported between two objects of the same type.
For structures it is field to field assignment. For enumerations and unions
of primitives or trivially copiable types it the same as memcpy.

### Equality: ?==? ?!=?
Both equality operations can be implemented by negating the result of the
other operations.

For structures: Equality can be implement by checking equality on each pair of
matching fields and taking the logical and of the results. Inequality can be
implemented by checking inequality on each pair of matching fields and taking
the logical or of the results.

Both logical operations could be short circuiting. Without side effects it is
purely an optimization.

For enumerations: Both operations are the same as on the underlying integral.

For unions: If it is assumed that the different branches represent different
views of the same data and this data is primitive, than bit-wise comparisons
can be used.

### Comparison: ?<? ?>? ?<=? ?>=?
Less than can be implemented by flipping the arguments on greater than.
Greater than can be implemented by flipping less then. Less than or equal to
can be implemented by flipping greater than or equal to. Greater than or equal
to can be implemented by flipping less than or equal to.

Less than or equal to can be implemented by using less than, equals and taking
the or of the results. Greater than or equal to can be implemented by using
greater than, equals and taking the or of the results.

> The trick of negating comparisons is not used. As an example ?<? is not
> (boolean) not ?>=? unless the type is strictly ordered. For operator based
> overloads that might not be true in very reasonable implementations so it is
> not assumed.

Opposite less than can be implemented as less than or equal to and not equal
to. Greater than can be implemented as greater than or equal to and not equal
to.

For enumerations: Enumerations that represent one of all operations are the
same as on the underlying integral. Enumerations that represent a set of
options could replace less then with subset of and greator than with superset
of and use bit-wise masking to implement those operations.

### Binary & Relative Assignment Operators: ?_? ?_=?
This applies to each operator in the form of `T ?_?(T, T);` for some type T
and has a matching relative assignment operator `T& ?_=?(T&, T)` where the
`_` in both is replaced by some string of operator characters.

The binary operator can be created by copying the left argument, using the
relative assignment with the right argument and returning the updated copy.

The relative assignment operator can be implemented by using the binary
operation to create a copy, then assigning the result to the left argument.
The left argument should then be returned. For the signature above it would
return by reference. The signature `T ?_=?(T&, T)` could also be supported in
which case it would return by copy.

### Minus: -? ?-?
Unary minus can be implemented by subtracting argument from the value created
from zero_t.

Binary minus can be implemented by negating (with unary minus) the right
argument and adding the result to the left argument.

### Increment & Decrement: ++? ?++ --? ?--
Either pre- operation can implemented by applying the post- operation and then
returning a reference to, or copy of, the updated value. Either post-
operation can be implemented by copying the argument, applying the pre-
operation to the original and returning the copy.

Pre-increment can be implemented by using addition assignment by the value
constructed from one_t. Pre-decrement can be implemented by using subtraction
assignment by the value from one_t.

Because many of the operations used have there own default implementations
(for example: ?+=? from ?+? or field-wise one_t construction) this list could
be expanded by replacing a function call with the default implementation for
that function. This might work for the post- operations generated from
relative assignment, the one_t constructed object and copying, but the logical
connection becomes weaker and weaker as that process continues.

### Bit Manipulation: ?|? ?&? ~? ?<<? ?>>?
No operation based construction is provided for bit manipulation operators.

For enumerations that are considered sets of flags: And returns a set with all
flags set in both operand sets, or returns a set with all flags set that are
set in either operand sets and not returns a set with all flags set that are
not set in the operand set.

> And it would be possible to actually implement this for any sized type and
> just do the bitwise operation and trust the user that it makes sense if they
> request it.

Also for set enumerations, the signature `T ?<<?(one_t, unsigned)` also has
some use, as it can be used to implement a loop that goes over each flag,
instead of each combination of flags.

### Logical Negation: !?
Not can be implemented by negating the result of a conversion to boolean, the
does not equal 0 test.

Circular Requirements
---------------------

There are several cases where there are two operators that can be implemented
with the other operator. If both are implemented that way calling either of
them could result in infinite recursion.

The simplest way to handle the issue would be to tell the user to not do that,
they are responsible for providing the base operations. This is C like but is
perhaps more error prone than it would save in work and if we do check we can
automatically use fallbacks.

Before generating any default implementations the compiler should generate
a list of everything it has been requested and ignore any generation methods
that would lead to chains instead of counting other defaults that could lead
to a loop. As a further improvment this could be done selectively to break
rings while allowing chains of non-recurive implementations.

For instance if both ?==? and ?!=? are requested they cannot both be defined
as the negation of each other. In the simple version they would both be
generated by introspection on the declaration. With the more selective version
one could be generated by introspection and the other by negating that result.

However there are still ways to get around this by placing the function
definitions in different translation units or defining a function that uses
an operator that is default generated to use it. Searching for all these cases
is probably not worth it, although checking for some might be useful warnings.
