hasElaborateCopyConstructor bug?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Jun 2 19:29:22 UTC 2019


On Sunday, June 2, 2019 8:32:16 AM MDT Paul Backus via Digitalmars-d-learn 
wrote:
> On Sunday, 2 June 2019 at 06:59:02 UTC, Jonathan M Davis wrote:
> > Almost certainly, hasElaborateCopyConstructor should be updated
> > to test for both postblit constructors and copy constructors,
> > since its purpose is to test for whether the type has a
> > user-defined copying function [...] Whether
> > hasElaborateCopyConstructor was the best name is debatable, but
> > it _does_ involve "elaborate" copying, and copy constructors
> > weren't actually in the language at the time. The documentation
> > is wonderfully confusing though in that it talks about copy
> > constructors and then says that a copy constructor is
> > introduced by defining this(this) for a struct. So, it
> > basically calls a postblit constructor a copy constructor.
>
> I've made the mistake in the past of trying to use
> hasElaborateCopyConstructor to test for the presence of
> __xpostblit, and I'm sure I'm not the only one. The name is quite
> misleading--even more so now that D has real copy constructors.
>
> If std.v2 ever materializes, we'll have an opportunity to fix
> papercuts like this. Until then, my preferred workaround is to
> use a renaming import:
>
> import std.traits: hasNontrivialCopy =
> hasElaborateCopyConstructor;

Why is it a mistake to use hasElaborateCopyConstructor to test for
__xpostblit? Because you're trying to test for __xpostblit for some purpose
other than determining whether the type is blittable? I'm not sure what
other reason there would be to test for __xpostblit though. Either way,
hasElaborateCopyConstructor currently checks for exactly that (with the
addition that it checks whether a static array has elements with
__xpostblit):

template hasElaborateCopyConstructor(S)
{
    static if (__traits(isStaticArray, S) && S.length)
    {
        enum bool hasElaborateCopyConstructor = hasElaborateCopyConstructor!
(typeof(S.init[0]));
    }
    else static if (is(S == struct))
    {
        enum hasElaborateCopyConstructor = __traits(hasMember, S, 
"__xpostblit");
    }
    else
    {
        enum bool hasElaborateCopyConstructor = false;
    }
}

My point was that given the purpose of hasElaborateCopyConstructor, updating
it to test for both a postblit constructor and copy constructor would be
appropriate. In fact, the fact that it hasn't been means that the
introduction of copy constructors has broken existing code (or at least that
such code won't interact correctly with structs that have copy
constructors). There should be no need to rename the trait, just update it,
and whether it uses the name "elaborate" or "non-trivial" is pretty much
irrelevant. Personally, I probably would have chosen hasNonTrivial over
hasElaborate, but they mean the same thing, and we have
hasElaborateDestructor for the corresponding test for destructors and
hasElaborateAssign for the corresponding test for assignment. It really
doesn't make sense to change the name at this point.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list