[LLVMdev] object construction patterns and unique_ptr

Chandler Carruth chandlerc at google.com
Wed Jun 20 00:28:20 PDT 2012


On Tue, Jun 19, 2012 at 11:18 AM, Jeffrey Yasskin <jyasskin at google.com>wrote:

> On Jun 18, 2012 1:24 PM, "Nick Kledzik" <kledzik at apple.com> wrote:
> >
> > On Jun 16, 2012, at 3:51 PM, Chris Lattner wrote:
> > > On Jun 15, 2012, at 3:48 PM, Nick Kledzik wrote:
> > >
> > >> In lld we have a Reader class which is a factory that takes .o
> file(s) and produces an in memory lld::File object(s).  But in doing so,
> there could be I/O errors (file not readable) or file may be malformed.  We
> are also using C++11 in lld, so we use std::unique_ptr for managing object
> ownership.
> > >>
> > >> The Reader class currently has an interface that can be simplified
> down to:
> > >>
> > >>   virtual error_code readFile(StringRef path,
> std::unique_ptr<lld::File> &result);
> > >>
> > >> But this interface has become awkward to use. There are two "return"
> values.  This method is a unique_ptr "source" but the use of a by-refernce
> parameter means you have to start with an uninitialized unique_ptr and the
> readFile() has to std::move() into it.   unique_ptr is much nicer to use as
> a return value.
> > >
> > > Not a c++'11 expert here, but does a returning an std::tuple work?
> > I talked to Howard about that.  It does work, but it is cumbersome.
>  Either:
> >
> > std::tuple<std::unique_ptr<lld::File>, error_code>  result =
> reader.readFile(path);
> >
>
> I suggest an error_or<T> class that can be combined with any result type,
> not just File. It could be implemented with a fully generic variant class,
> but the interface would likely be better with some specialization to errors.
>
I also really like the variant design. It has a few important advantages
IMO:

1) No pointers or heap allocations. These make code more bug prone and can
needlessly hurt optimizers. (although the latter is hopefully not relevant
in this specific case)

2) No "error" state in the file object. Either you have a fully constructed
object or you don't.

3) An explicit API to check and instrument whether an error has occured.
For example, it is harder to "forget" to check the error, and carry on
manipulating the file. The implementation can assert in debug builds to
catch this early, etc.

4) Doesn't require polymorphic types (but they can be supported if needed).
Essentially, you can wrap a *specific* file type, rather than being forced
to use some generic file type.


One interesting possibility is that you can grow the same pattern to
different levels of complexity as needed (and thus keep it as simple as
possible as long as possible):

error_or<T>  -- wraps the existing error_code with a nice interface
linker_error_or<T> -- wraps both an error_code and some linker specific
error handling logic
file_error_or<T> -- provides completely custom error information specific
to file-loading-errors.


I'm not saying which (if any) of these would be appropriate, just pointing
out that this pattern can be followed to greater and lesser degrees of
specificity.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120620/ffc3b999/attachment.html>


More information about the llvm-dev mailing list