> On May 12, 2016, at 2:47 PM, Richard Smith <[email protected]> wrote:
> On 12 May 2016 at 13:34, John McCall <[email protected]
> <mailto:[email protected]>> wrote:
>> On May 12, 2016, at 12:07 PM, Richard Smith <[email protected]
>> <mailto:[email protected]>> wrote:
>> On 12 May 2016 at 11:45, John McCall <[email protected]
>> <mailto:[email protected]>> wrote:
>>> On May 6, 2016, at 2:29 PM, Richard Smith <[email protected]
>>> <mailto:[email protected]>> wrote:
>>> Per http://wg21.link/p0136r1 <http://wg21.link/p0136r1> an inheriting
>>> constructor declaration no longer results in the implicit synthesis of
>>> derived class constructors, and instead the behavior of a call to an
>>> inherited constructor is that:
>>>
>>> 1) the portion of a hypothetical defaulted default constructor prior to
>>> the base constructor invocation is executed, then
>>> 2) the inherited constructor is invoked, then
>>> 3) the portion of a hypothetical defaulted default constructor after the
>>> base constructor invocation is executed
>>>
>>> There are a couple of obvious ways we could avoid emitting the code for (1)
>>> and (3) in every inherited constructor call site:
>>
>> This only affects interoperation to the extent that it's done with vague
>> linkage, since as far as I know there's no way to give an inherited
>> constructor a strong definition.
>>
>> Yes.
>>
>> I think we should recommend using (A) in all cases where it's possible,
>> which as far as I know is everything except variadic constructors, and then
>> just inline all the appropriate initialization for variadics.
>>
>> OK, sounds fine to me. I don't really think the variadic case will come up
>> enough to worry about it. The other benefit of the prefix/suffix functions
>> is that we can factor out some of the duplication from the CI functions
>> themselves, but that seems very much like a secondary benefit.
>
> I mean, if we wanted to, we could apply that as a code-size optimization
> across ordinary constructors when we happen to notice that they have
> equivalent initializers.
>
>> (A) has to deal with both constructor variants, though.
>>
>> Good point. Maybe CI1<type> / CI2<type>?
>
> That makes sense to me if we do need to distinguish inherited constructors.
>
>>
>> Is there a reason we can't just continue to mangle the symbol as a C1 or C2
>> in the derived class? Just concern about ODR differences when there happens
>> to be a non-trivially-copyable type passed by value?
>>
>> For a C2 constructor that inherits a constructor from a virtual base, the
>> signature will be different from the old approach, because parameters will
>> no longer be passed at all (whereas before they were passed and discarded).
>> That's probably fine for most calling conventions, but seems risky in
>> general. [As a further optimization, we could share the same C2 constructor
>> for all inherited constructors that inherit from the same (set of) virtual
>> base(s), but I'm not sure that's worth putting into the ABI.]
>>
>> I'm also concerned about there being edge cases where overload resolution
>> could pick between constructors from two different base classes despite them
>> mangling the same. Highly-contrived example:
>>
>> constexpr int f(), g();
>> struct A { template<int = f()> A(int); };
>> struct B { template<int = g()> B(int); };
>> struct C : A, B {
>> using A::A;
>> using B::B;
>> };
>>
>> TU1:
>> constexpr int f() { return 0; }
>> C c(0);
>> constexpr int g() { return 0; }
>>
>> TU2:
>> constexpr int g() { return 0; }
>> C c(0);
>> constexpr int f() { return 0; }
>>
>> I think this is valid, with TU1 calling A(int) and TU2 calling B(int).
>
> That is a really amazing example. I feel enriched. :)
>
> C++ truly is a remarkable language.
>
> I'm surprised that the language model here has changed so much, though. The
> inherited constructors really aren't treated as declarations in the derived
> class? I would expect it to be a much better language model to treat them as
> declarations that just have non-standard semantics when invoked.
>
> The new semantic model fixes a whole laundry list of issues caused by
> building separate declarations for them -- we want to access-check the
> constructor as if it were in the base class, we want to handle default
> arguments as we would for the base class overload set, we want failures in
> the delegating call in the inheriting constructor count as "immediate
> context" for the purposes of SFINAE, and so on (see wg21.link/cwg1573,
> wg21.link/cwg1645, wg21.link/cwg1715, wg21.link/cwg1736, wg21.link/cwg1941,
> wg21.link/cwg1991). Synthesizing a constructor / constructor template makes
> it hard to get these cases right, as well as giving the wrong semantics for
> argument passing.
Alright, I accept that we should mangle these differently, and 'CI' <variant>
<type> seems reasonable.
John.
_______________________________________________
cxx-abi-dev mailing list
[email protected]
http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev