lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] libstdc++ in gcc-7.3.0: std::vector<incomplete_type>


From: Vadim Zeitlin
Subject: Re: [lmi] libstdc++ in gcc-7.3.0: std::vector<incomplete_type>
Date: Thu, 26 Apr 2018 01:03:23 +0200

On Wed, 25 Apr 2018 20:29:21 +0000 Greg Chicares <address@hidden> wrote:

GC> On 2018-04-25 16:36, Vadim Zeitlin wrote:
GC> > On Wed, 25 Apr 2018 00:45:58 +0000 Greg Chicares <address@hidden> wrote:
GC> >
GC> [...moved inlines out of line, and wroite an explicit dtor out of line,
GC> but it still wouldn't compile...]
GC> > 
GC> >  Sorry, there is a third one, too.
GC> 
GC> I.e., replace implicit copy ctor with an explicit one written out of line.
GC> 
GC> I went back to the gcc messages I was staring at last night, and the best
GC> interpretation I can come up with [highly edited to reduce size] is:
GC> 
GC> /c++/bits/stl_vector.h: In instantiation of 
'<wx_table_generator::column_info>'
GC> /c++/bits/stl_vector.h:   required from
GC>   std::vector<wx_table_generator::column_info>::vector(const 
std::vector<T>&)
GC> 
GC> I.e., a std::vector copy ctor couldn't be generated, and from that I am
GC> to reason that the copy ctor of a class that contains such a vector cannot
GC> be generated because it's implicitly declared. That seems like a non-obvious
GC> deduction.

 Unfortunately the compiler error message is just poor (and, for once, this
applies to clang too). It would help a lot if it continued with the
"required from" chain and mentioned that it all stems from the need to
copy an illustration_table_generator object. But it doesn't and,
ironically, I think it might be truncating the error message intentionally
in order to hide "unimportant" details -- except here they're important.

GC> Is there a set of best practices that would have helped here?

 I don't know if it can be called a best practice, but the solution is to
just never define any ctors (including the implicitly-generated ones) or
dtor in the header file if a class uses a container with an incomplete
type. Together with not using the name of the container variable in any way
explicitly, this is both necessary and sufficient for the code to compile.

GC> In the C++98 era, I strove to implement all of a class's member functions
GC> in the same file--either all inline in the '.hpp' file where they were
GC> declared, or all out of line in a separate '.cpp' file--and especially to
GC> keep all (implicit or explicit) ctors and dtors in one place or the other,
GC> to make sure both were called from the same side of a DLL barrier. That
GC> often meant declaring all special member functions explicitly, and defining
GC> them with "{}" as the function body.

 I'm not sure why having an inline ctor or dtor on the same side of the DLL
barrier would help with the DLL-related problems. There are 2 such
problems: one is using different compiler options when compiling the DLL
and the main executable, resulting in different class layout. This is fatal
and can't be worked around anyhow. The other one is allocating memory in
the executable and freeing it in the DLL, or vice versa, which doesn't work
if they use different CRT versions. This one is best solved by using the
same CRT DLL (which lmi does) and defining all class methods inside the DLL
is neither sufficient nor required to solve it.

GC> Here, we had to do something very similar.

 The solution is similar, but the cause of the problem is different and the
manifestation of the problem is much nicer: it results in compile-time
errors instead of run-time crashes.

GC> How much of my C++98 defensive practice is still useful? Should any
GC> part of it be omitted, or anything new be added?

 I don't see any reason to follow that defensive practice any more. Having
a container of an incomplete type is a rare case and results in
compile-time errors when ctor/dtor can't be defined inline, so it's enough
to just move them out of line in this case. But there is really no need to
do anything systematically for all the other classes.

GC> The only thing I'm fairly sure of is that "=default;" can now replace
GC> "{}".

 This is still true, of course.

 Regards,
VZ


reply via email to

[Prev in Thread] Current Thread [Next in Thread]