Re: Are clang++ and libc++ compatible?

From: John Baldwin <jhb_at_freebsd.org>
Date: Tue, 12 Nov 2013 13:21:07 -0500
On Tuesday, November 12, 2013 1:11:04 pm Eitan Adler wrote:
> On Tue, Nov 12, 2013 at 11:54 AM, Steve Kargl
> <sgk_at_troutmask.apl.washington.edu> wrote:
> > On Tue, Nov 12, 2013 at 04:38:17PM +0000, David Chisnall wrote:
> >> On 12 Nov 2013, at 16:32, Steve Kargl <sgk_at_troutmask.apl.washington.edu> 
wrote:
> >>
> >>> Trying to build news/pan with clang++ dies with
> >>>
> >>> gmake[3]: Entering directory 
`/usr/ports/news/pan/work/pan-0.139/pan/general'
> >>>  CXX    file-util.o
> >>> In file included from file-util.cc:38:
> >>> In file included from ./log.h:26:
> >>> /usr/include/c++/v1/deque:907:49: error: invalid application of 'sizeof' 
to an
> >>>      incomplete type 'value_type' (aka 'pan::Log::Entry')
> >>>    static const difference_type __block_size = sizeof(value_type) < 256 
? 4...
> >>>
> >>> Anyone know how to fix either clang++ or libc++?
> >>
> >> The error here does not appear to be in clang or libc++, but in the
> >> use by the thing that you are compiling.
> >> This is saying that you have tried to create a 
std::dequeu<pan::Log::Entry>,
> >> but pan::Log::Entry is a forward declaration and so the template
> >> instantiation fails.
> >> The fix is to move the definition of pan::Log::Entry such that it
> >> is visible at the time of its use.
> >>
> >
> > I don't know C++, but it is at all like C, then the header files
> > are normally placed at the top of a file before one's code.  In
> > this case, the code in news/pan/work/pan-0.139/pan/general/log.h
> > looks like (where I've striped comment to keep it short)
> >
> > #ifndef __Log_h__
> > #define __Log_h__
> >
> > #include <ctime>
> > #include <set>
> > #include <string>
> > #include <deque>
> >
> > namespace pan
> > {
> >   class Log
> >   {
> >     public:
> >       enum Severity {
> >         PAN_SEVERITY_INFO = 1,
> >         PAN_SEVERITY_ERROR = 2,
> >         PAN_SEVERITY_URGENT = (1<<10)
> >       };
> >
> >       struct Entry {
> >         time_t date;
> >         Severity severity;
> >         std::deque<Entry> messages;
> >         std::string message;
> >         bool is_child;
> >         Entry() : is_child(false) { }
> >       };
> >
> >       void add_entry(Entry& e, std::deque<Entry>& list);
> >
> >
> > Are you saying that I need to move '#include <deque>' to
> > the location above the 'void add_entry(...)' line?
> 
> The problem here is that the code is trying to make a std::deque of
> the type Entry before Entry is fully defined.
> This is nearly identical to the problem in the simplified C code below:
> 
> struct foo {
> struct foo bar;
> }

Except it isn't.  It's declaring the head of a container.  This is more
like:

	struct foo {
		TAILQ_HEAD(, foo) messages;
	};

The problem is that unlike the queue macros (which are broken out into
chunks), the compiler has to instantiate all of std::deque<> even though
it will only use a portion of its definition.  I understand why this is
a limitation of C++, but it's not quite as brain damaged as your
example.  The above would not be unreasonable if the foo objects should
be stored in a tree and messages was a list of the child nodes.

Depending on how this library works you might be able to shim around this by 
having the dequeue store pointers instead of Entry structs.

-- 
John Baldwin
Received on Tue Nov 12 2013 - 18:54:46 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:44 UTC