More gdb::optional features
authorPedro Alves <palves@redhat.com>
Tue, 18 Apr 2017 20:39:24 +0000 (21:39 +0100)
committerPedro Alves <palves@redhat.com>
Tue, 18 Apr 2017 22:48:41 +0000 (23:48 +0100)
commit22796e972f18c5601cecb0251222411a352836b6
tree0e2cdd295c54b35894588485dda6d821648540d7
parenta7fc9b6193f830293066479aa439cea924418393
More gdb::optional features

Currently we can't use gdb::optional<T> as function return type,
because gdb::optional's copy ctor is deleted.  For example, with:

  gdb::optional<int> function ()
  {
    gdb::optional<int> opt;
    ....
    return opt;

we get:

  src/gdb/foo.c: In function ‘gdb::optional<int> foo()’:
  src/gdb/foo.c:75:10: error: use of deleted function ‘gdb::optional<T>::optional(const gdb::optional<T>&) [with T = int]’
     return opt;
    ^
  In file included from src/gdb/foo.c:68:0:
  src/gdb/common/gdb_optional.h:53:3: note: declared here
     optional (const optional &other) = delete;
     ^

I started by fixing that, and then ran into another missing feature,
also fixed by this patch.

The next feature I'm missing most from gdb::optional<T> compared to
std::optional<T> is construction/move/assignment from a T, instead of
having to default construct an gdb::optional and then use
optional::emplace(....).

For example:
  gdb::optional<std::string> function ()
  {
    gdb::optional<std::string> opt;
    std::string str;
    ...
    opt.emplace (std::move (str));
    return opt;
vs
  gdb::optional<std::string> function ()
  {
    std::string str;
    ...
    return str;

The copy/move ctor/assign methods weren't initialy implemented because
std::optional supports construction from a type U if U is convertible
to T too, and has rules to decide whether the ctors are
explicit/implicit based on that, and rules for whether the ctor should
be trivial or not, etc., which leads to a much more complicated
implementation.

If we stick to supporting copy/move construction/assignment of/to an
optional<T> from exactly only optional<T> and T, then all that
conversion-related complication disappears, and we still gain
convenience in most use cases.

The patch also makes emplace return a reference to the constructor
object, per C++17 std::optional, and adds a reset method, againt
because std::optional has one and it's trivial to support it.  These
two changes are a requirement of the gdb::optional unit testing patch
that will follow.

gdb/ChangeLog:
2017-04-18  Pedro Alves  <palves@redhat.com>

* common/gdb_optional.h: Include common/traits.h.
(in_place_t): New type.
(in_place): New constexpr variable.
(optional::optional): Remove member initialization of
m_instantiated.
(optional::optional(in_place_t...)): New constructor.
(optional::~optional): Use reset.
(optional::optional(const optional&)): New.
(optional::optional(const optional&&)): New.
(optional::optional(T &)): New.
(optional::optional(T &&)): New.
(operator::operator=(const optional &)): New.
(operator::operator=(optional &&)): New.
(operator::operator= (const T &))
(operator::operator= (T &&))
(operator::emplace (Args &&... args)): Return a T&.  Use reset.
(operator::reset): New.
(operator::m_instantiated):: Add in-class initializer.
* common/traits.h: Include <type_traits>.
(struct And): New types.
gdb/ChangeLog
gdb/common/gdb_optional.h
gdb/common/traits.h