Aggregate initialization in the presence of deleted constructors

Abstract

This paper describes an alternative solution to Timur Doumler's paper
for making class types with user-declared constructors non-aggregates.
The gist of the difference is that this alternative treats implicitly
deleted and explicitly deleted constructors the same way, and provides
a different design principle - in the approach described, deleted
constructors subtract from an overload set but do not necessarily
establish such a set, i.e. they turn off specific forms of aggregate
initialization but not all of them.
.

Jacksonville 2018 discussion feedback

In Jacksonville, when discussing P0960, the following feedback was
given by EWG:

Incorporate ban brace-initializing an object if it would be plausible that it would use a deleted constructor? 11 | 14 | 5 | 0 | 3

This paper and Timur's paper separate out aggregate initialization
in the presence of deleted constructors.

I'm not sure we can do much more than guesswork on what
does or does not make sense to programmers, but to me,
it makes sense that deleting a default constructor
deletes initializations that don't provide values, whereas
initializations that do provide values are unaffected
by it.

To be fair, there are other examples where it's anything
but obvious what is or is not obvious. :) Such as

The non-obvious part is that user-declaring a non-deleted
constructor would make that constructor the only valid
initialization signature (except for copy/move, from a single object),
but user-declaring a deleted constructor doesn't do that.
I admit that the suggested mental model of "deleted constructor
subtracts from the overload set but doesn't necessarily establish it"
is not the strongest model I've seen. It does seem workable, though. It
makes sense to me that the user wanted to remove a two-parameter
signature from the set of valid initialization signatures. The rest
is convenience; if we believe that it's likely that such selective
removal is expected, this is a more convenient approach than
saying "if you ever declare a constructor, you will need to
declare the full set". We already require so for non-deleted constructors,
though.

Pseudo-wording

It's perhaps easier to understand my approach in terms
of wording. So, in [dcl.init.list]/3.4, we do something like

Otherwise, if T is an aggregate, constructors are considered. If
a viable constructor is found, but initializing T with a constructor
would be ill-formed, the program
is ill-formed. Otherwise, aggregate initialization is performed.