Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6554 serge 1
//  -*- C++ -*-
2
 
3
// Copyright (C) 2013-2015 Free Software Foundation, Inc.
4
//
5
// This file is part of the GNU ISO C++ Library.  This library is free
6
// software; you can redistribute it and/or modify it under the
7
// terms of the GNU General Public License as published by the
8
// Free Software Foundation; either version 3, or (at your option)
9
// any later version.
10
 
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
// GNU General Public License for more details.
15
 
16
// Under Section 7 of GPL version 3, you are granted additional
17
// permissions described in the GCC Runtime Library Exception, version
18
// 3.1, as published by the Free Software Foundation.
19
 
20
// You should have received a copy of the GNU General Public License and
21
// a copy of the GCC Runtime Library Exception along with this program;
22
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
// .
24
 
25
/** @file experimental/optional
26
 *  This is a TS C++ Library header.
27
 */
28
 
29
#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
30
#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
31
 
32
/**
33
 * @defgroup experimental Experimental
34
 *
35
 * Components specified by various Technical Specifications.
36
 *
37
 * As indicated by the std::experimental namespace and the  header paths,
38
 * the contents of these Technical Specifications are experimental and not
39
 * part of the C++ standard. As such the interfaces and implementations may
40
 * change in the future, and there is  no guarantee of compatibility
41
 * between different GCC releases  for these features.
42
 */
43
 
44
#if __cplusplus <= 201103L
45
# include 
46
#else
47
 
48
#include 
49
#include 
50
#include 
51
#include 
52
#include 
53
#include 
54
#include 
55
#include 
56
 
57
namespace std _GLIBCXX_VISIBILITY(default)
58
{
59
namespace experimental
60
{
61
inline namespace fundamentals_v1
62
{
63
_GLIBCXX_BEGIN_NAMESPACE_VERSION
64
 
65
  /**
66
   * @defgroup optional Optional values
67
   * @ingroup experimental
68
   *
69
   * Class template for optional values and surrounding facilities, as
70
   * described in n3793 "A proposal to add a utility class to represent
71
   * optional objects (Revision 5)".
72
   *
73
   * @{
74
   */
75
 
76
#define __cpp_lib_experimental_optional 201411
77
 
78
  // All subsequent [X.Y.n] references are against n3793.
79
 
80
  // [X.Y.4]
81
  template
82
    class optional;
83
 
84
  // [X.Y.5]
85
  /// Tag type for in-place construction.
86
  struct in_place_t { };
87
 
88
  /// Tag for in-place construction.
89
  constexpr in_place_t in_place { };
90
 
91
  // [X.Y.6]
92
  /// Tag type to disengage optional objects.
93
  struct nullopt_t
94
  {
95
    // Do not user-declare default constructor at all for
96
    // optional_value = {} syntax to work.
97
    // nullopt_t() = delete;
98
 
99
    // Used for constructing nullopt.
100
    enum class _Construct { _Token };
101
 
102
    // Must be constexpr for nullopt_t to be literal.
103
    explicit constexpr nullopt_t(_Construct) { }
104
  };
105
 
106
  // [X.Y.6]
107
  /// Tag to disengage optional objects.
108
  constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
109
 
110
  // [X.Y.7]
111
  /**
112
   *  @brief Exception class thrown when a disengaged optional object is
113
   *  dereferenced.
114
   *  @ingroup exceptions
115
   */
116
  class bad_optional_access : public logic_error
117
  {
118
  public:
119
    bad_optional_access() : logic_error("bad optional access") { }
120
 
121
    // XXX This constructor is non-standard. Should not be inline
122
    explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
123
 
124
    virtual ~bad_optional_access() noexcept = default;
125
  };
126
 
127
  void
128
  __throw_bad_optional_access(const char*)
129
  __attribute__((__noreturn__));
130
 
131
  // XXX Does not belong here.
132
  inline void
133
  __throw_bad_optional_access(const char* __s)
134
  { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
135
 
136
  template
137
    struct _Has_addressof_mem : std::false_type { };
138
 
139
  template
140
    struct _Has_addressof_mem<_Tp,
141
         __void_t().operator&() )>
142
      >
143
    : std::true_type { };
144
 
145
  template
146
    struct _Has_addressof_free : std::false_type { };
147
 
148
  template
149
    struct _Has_addressof_free<_Tp,
150
         __void_t()) )>
151
      >
152
    : std::true_type { };
153
 
154
  /**
155
    * @brief Trait that detects the presence of an overloaded unary operator&.
156
    *
157
    * Practically speaking this detects the presence of such an operator when
158
    * called on a const-qualified lvalue (i.e.
159
    * declval<_Tp * const&>().operator&()).
160
    */
161
  template
162
    struct _Has_addressof
163
    : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type
164
    { };
165
 
166
  /**
167
    * @brief An overload that attempts to take the address of an lvalue as a
168
    * constant expression. Falls back to __addressof in the presence of an
169
    * overloaded addressof operator (unary operator&), in which case the call
170
    * will not be a constant expression.
171
    */
172
  template::value, int>...>
173
    constexpr _Tp* __constexpr_addressof(_Tp& __t)
174
    { return &__t; }
175
 
176
  /**
177
    * @brief Fallback overload that defers to __addressof.
178
    */
179
  template::value, int>...>
180
    inline _Tp* __constexpr_addressof(_Tp& __t)
181
    { return std::__addressof(__t); }
182
 
183
  /**
184
    * @brief Class template that holds the necessary state for @ref optional
185
    * and that has the responsibility for construction and the special members.
186
    *
187
    * Such a separate base class template is necessary in order to
188
    * conditionally enable the special members (e.g. copy/move constructors).
189
    * Note that this means that @ref _Optional_base implements the
190
    * functionality for copy and move assignment, but not for converting
191
    * assignment.
192
    *
193
    * @see optional, _Enable_special_members
194
    */
195
  template
196
	   !is_trivially_destructible<_Tp>::value>
197
    class _Optional_base
198
    {
199
    private:
200
      // Remove const to avoid prohibition of reusing object storage for
201
      // const-qualified types in [3.8/9]. This is strictly internal
202
      // and even optional itself is oblivious to it.
203
      using _Stored_type = remove_const_t<_Tp>;
204
 
205
    public:
206
      // [X.Y.4.1] Constructors.
207
 
208
      // Constructors for disengaged optionals.
209
      constexpr _Optional_base() noexcept
210
      : _M_empty{} { }
211
 
212
      constexpr _Optional_base(nullopt_t) noexcept
213
      : _Optional_base{} { }
214
 
215
      // Constructors for engaged optionals.
216
      constexpr _Optional_base(const _Tp& __t)
217
      : _M_payload(__t), _M_engaged(true) { }
218
 
219
      constexpr _Optional_base(_Tp&& __t)
220
      : _M_payload(std::move(__t)), _M_engaged(true) { }
221
 
222
      template
223
        constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
224
        : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
225
 
226
      template
227
               enable_if_t
228
                                            initializer_list<_Up>&,
229
                                            _Args&&...>::value,
230
                           int>...>
231
        constexpr explicit _Optional_base(in_place_t,
232
                                          initializer_list<_Up> __il,
233
                                          _Args&&... __args)
234
        : _M_payload(__il, std::forward<_Args>(__args)...),
235
          _M_engaged(true) { }
236
 
237
      // Copy and move constructors.
238
      _Optional_base(const _Optional_base& __other)
239
      {
240
        if (__other._M_engaged)
241
          this->_M_construct(__other._M_get());
242
      }
243
 
244
      _Optional_base(_Optional_base&& __other)
245
      noexcept(is_nothrow_move_constructible<_Tp>())
246
      {
247
        if (__other._M_engaged)
248
          this->_M_construct(std::move(__other._M_get()));
249
      }
250
 
251
      // [X.Y.4.3] (partly) Assignment.
252
      _Optional_base&
253
      operator=(const _Optional_base& __other)
254
      {
255
        if (this->_M_engaged && __other._M_engaged)
256
          this->_M_get() = __other._M_get();
257
        else
258
	  {
259
	    if (__other._M_engaged)
260
	      this->_M_construct(__other._M_get());
261
	    else
262
	      this->_M_reset();
263
	  }
264
 
265
        return *this;
266
      }
267
 
268
      _Optional_base&
269
      operator=(_Optional_base&& __other)
270
      noexcept(__and_,
271
		      is_nothrow_move_assignable<_Tp>>())
272
      {
273
	if (this->_M_engaged && __other._M_engaged)
274
	  this->_M_get() = std::move(__other._M_get());
275
	else
276
	  {
277
	    if (__other._M_engaged)
278
	      this->_M_construct(std::move(__other._M_get()));
279
	    else
280
	      this->_M_reset();
281
	  }
282
	return *this;
283
      }
284
 
285
      // [X.Y.4.2] Destructor.
286
      ~_Optional_base()
287
      {
288
        if (this->_M_engaged)
289
          this->_M_payload.~_Stored_type();
290
      }
291
 
292
      // The following functionality is also needed by optional, hence the
293
      // protected accessibility.
294
    protected:
295
      constexpr bool _M_is_engaged() const noexcept
296
      { return this->_M_engaged; }
297
 
298
      // The _M_get operations have _M_engaged as a precondition.
299
      constexpr _Tp&
300
      _M_get() noexcept
301
      { return _M_payload; }
302
 
303
      constexpr const _Tp&
304
      _M_get() const noexcept
305
      { return _M_payload; }
306
 
307
      // The _M_construct operation has !_M_engaged as a precondition
308
      // while _M_destruct has _M_engaged as a precondition.
309
      template
310
        void
311
        _M_construct(_Args&&... __args)
312
        noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
313
        {
314
          ::new (std::__addressof(this->_M_payload))
315
            _Stored_type(std::forward<_Args>(__args)...);
316
          this->_M_engaged = true;
317
        }
318
 
319
      void
320
      _M_destruct()
321
      {
322
        this->_M_engaged = false;
323
        this->_M_payload.~_Stored_type();
324
      }
325
 
326
      // _M_reset is a 'safe' operation with no precondition.
327
      void
328
      _M_reset()
329
      {
330
        if (this->_M_engaged)
331
          this->_M_destruct();
332
      }
333
 
334
    private:
335
      struct _Empty_byte { };
336
      union {
337
          _Empty_byte _M_empty;
338
          _Stored_type _M_payload;
339
      };
340
      bool _M_engaged = false;
341
    };
342
 
343
  /// Partial specialization that is exactly identical to the primary template
344
  /// save for not providing a destructor, to fulfill triviality requirements.
345
  template
346
    class _Optional_base<_Tp, false>
347
    {
348
    private:
349
      using _Stored_type = remove_const_t<_Tp>;
350
 
351
    public:
352
      constexpr _Optional_base() noexcept
353
      : _M_empty{} { }
354
 
355
      constexpr _Optional_base(nullopt_t) noexcept
356
      : _Optional_base{} { }
357
 
358
      constexpr _Optional_base(const _Tp& __t)
359
      : _M_payload(__t), _M_engaged(true) { }
360
 
361
      constexpr _Optional_base(_Tp&& __t)
362
      : _M_payload(std::move(__t)), _M_engaged(true) { }
363
 
364
      template
365
        constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
366
        : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
367
 
368
      template
369
               enable_if_t
370
                                            initializer_list<_Up>&,
371
                                            _Args&&...>::value,
372
			   int>...>
373
        constexpr explicit _Optional_base(in_place_t,
374
                                          initializer_list<_Up> __il,
375
                                          _Args&&... __args)
376
        : _M_payload(__il, std::forward<_Args>(__args)...),
377
          _M_engaged(true) { }
378
 
379
      _Optional_base(const _Optional_base& __other)
380
      {
381
        if (__other._M_engaged)
382
          this->_M_construct(__other._M_get());
383
      }
384
 
385
      _Optional_base(_Optional_base&& __other)
386
      noexcept(is_nothrow_move_constructible<_Tp>())
387
      {
388
        if (__other._M_engaged)
389
          this->_M_construct(std::move(__other._M_get()));
390
      }
391
 
392
      _Optional_base&
393
      operator=(const _Optional_base& __other)
394
      {
395
	if (this->_M_engaged && __other._M_engaged)
396
	  this->_M_get() = __other._M_get();
397
	else
398
	  {
399
	    if (__other._M_engaged)
400
	      this->_M_construct(__other._M_get());
401
	    else
402
	      this->_M_reset();
403
	  }
404
	return *this;
405
      }
406
 
407
      _Optional_base&
408
      operator=(_Optional_base&& __other)
409
      noexcept(__and_,
410
		      is_nothrow_move_assignable<_Tp>>())
411
      {
412
	if (this->_M_engaged && __other._M_engaged)
413
	  this->_M_get() = std::move(__other._M_get());
414
	else
415
	  {
416
	    if (__other._M_engaged)
417
	      this->_M_construct(std::move(__other._M_get()));
418
	    else
419
	      this->_M_reset();
420
	  }
421
	return *this;
422
      }
423
 
424
      // Sole difference
425
      // ~_Optional_base() noexcept = default;
426
 
427
    protected:
428
      constexpr bool _M_is_engaged() const noexcept
429
      { return this->_M_engaged; }
430
 
431
      _Tp&
432
      _M_get() noexcept
433
      { return _M_payload; }
434
 
435
      constexpr const _Tp&
436
      _M_get() const noexcept
437
      { return _M_payload; }
438
 
439
      template
440
        void
441
        _M_construct(_Args&&... __args)
442
        noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
443
        {
444
          ::new (std::__addressof(this->_M_payload))
445
            _Stored_type(std::forward<_Args>(__args)...);
446
          this->_M_engaged = true;
447
        }
448
 
449
      void
450
      _M_destruct()
451
      {
452
        this->_M_engaged = false;
453
        this->_M_payload.~_Stored_type();
454
      }
455
 
456
      void
457
      _M_reset()
458
      {
459
        if (this->_M_engaged)
460
          this->_M_destruct();
461
      }
462
 
463
    private:
464
      struct _Empty_byte { };
465
      union
466
      {
467
	_Empty_byte _M_empty;
468
	_Stored_type _M_payload;
469
      };
470
      bool _M_engaged = false;
471
    };
472
 
473
  /**
474
    * @brief Class template for optional values.
475
    */
476
  template
477
    class optional
478
    : private _Optional_base<_Tp>,
479
      private _Enable_copy_move<
480
        // Copy constructor.
481
        is_copy_constructible<_Tp>::value,
482
        // Copy assignment.
483
        __and_, is_copy_assignable<_Tp>>::value,
484
        // Move constructor.
485
        is_move_constructible<_Tp>::value,
486
        // Move assignment.
487
        __and_, is_move_assignable<_Tp>>::value,
488
        // Unique tag type.
489
        optional<_Tp>>
490
    {
491
      static_assert(__and_<__not_, nullopt_t>>,
492
			   __not_, in_place_t>>,
493
			   __not_>>(),
494
                    "Invalid instantiation of optional");
495
 
496
    private:
497
      using _Base = _Optional_base<_Tp>;
498
 
499
    public:
500
      using value_type = _Tp;
501
 
502
      // _Optional_base has the responsibility for construction.
503
      using _Base::_Base;
504
 
505
      // [X.Y.4.3] (partly) Assignment.
506
      optional&
507
      operator=(nullopt_t) noexcept
508
      {
509
        this->_M_reset();
510
        return *this;
511
      }
512
 
513
      template
514
        enable_if_t>::value, optional&>
515
        operator=(_Up&& __u)
516
        {
517
          static_assert(__and_,
518
			       is_assignable<_Tp&, _Up>>(),
519
                        "Cannot assign to value type from argument");
520
 
521
          if (this->_M_is_engaged())
522
            this->_M_get() = std::forward<_Up>(__u);
523
          else
524
            this->_M_construct(std::forward<_Up>(__u));
525
 
526
          return *this;
527
        }
528
 
529
      template
530
	void
531
	emplace(_Args&&... __args)
532
	{
533
	  static_assert(is_constructible<_Tp, _Args&&...>(),
534
			"Cannot emplace value type from arguments");
535
 
536
	  this->_M_reset();
537
	  this->_M_construct(std::forward<_Args>(__args)...);
538
	}
539
 
540
      template
541
        enable_if_t&,
542
				     _Args&&...>::value>
543
	emplace(initializer_list<_Up> __il, _Args&&... __args)
544
	{
545
	  this->_M_reset();
546
	  this->_M_construct(__il, std::forward<_Args>(__args)...);
547
	}
548
 
549
      // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
550
 
551
      // [X.Y.4.4] Swap.
552
      void
553
      swap(optional& __other)
554
      noexcept(is_nothrow_move_constructible<_Tp>()
555
               && noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
556
      {
557
        using std::swap;
558
 
559
        if (this->_M_is_engaged() && __other._M_is_engaged())
560
          swap(this->_M_get(), __other._M_get());
561
        else if (this->_M_is_engaged())
562
	  {
563
	    __other._M_construct(std::move(this->_M_get()));
564
	    this->_M_destruct();
565
	  }
566
        else if (__other._M_is_engaged())
567
	  {
568
	    this->_M_construct(std::move(__other._M_get()));
569
	    __other._M_destruct();
570
	  }
571
      }
572
 
573
      // [X.Y.4.5] Observers.
574
      constexpr const _Tp*
575
      operator->() const
576
      { return __constexpr_addressof(this->_M_get()); }
577
 
578
      _Tp*
579
      operator->()
580
      { return std::__addressof(this->_M_get()); }
581
 
582
      constexpr const _Tp&
583
      operator*() const&
584
      { return this->_M_get(); }
585
 
586
      constexpr _Tp&
587
      operator*()&
588
      { return this->_M_get(); }
589
 
590
      constexpr _Tp&&
591
      operator*()&&
592
      { return std::move(this->_M_get()); }
593
 
594
      constexpr const _Tp&&
595
      operator*() const&&
596
      { return std::move(this->_M_get()); }
597
 
598
      constexpr explicit operator bool() const noexcept
599
      { return this->_M_is_engaged(); }
600
 
601
      constexpr const _Tp&
602
      value() const&
603
      {
604
	return this->_M_is_engaged()
605
	  ?  this->_M_get()
606
	  : (__throw_bad_optional_access("Attempt to access value of a "
607
		                         "disengaged optional object"),
608
	     this->_M_get());
609
      }
610
 
611
      constexpr _Tp&
612
      value()&
613
      {
614
	return this->_M_is_engaged()
615
	  ?  this->_M_get()
616
	  : (__throw_bad_optional_access("Attempt to access value of a "
617
		                         "disengaged optional object"),
618
	     this->_M_get());
619
      }
620
 
621
      constexpr _Tp&&
622
      value()&&
623
      {
624
	return this->_M_is_engaged()
625
	  ?  std::move(this->_M_get())
626
	  : (__throw_bad_optional_access("Attempt to access value of a "
627
		                         "disengaged optional object"),
628
	     std::move(this->_M_get()));
629
      }
630
 
631
      constexpr const _Tp&&
632
      value() const&&
633
      {
634
	return this->_M_is_engaged()
635
	  ?  std::move(this->_M_get())
636
	  : (__throw_bad_optional_access("Attempt to access value of a "
637
		                         "disengaged optional object"),
638
	     std::move(this->_M_get()));
639
      }
640
 
641
      template
642
	constexpr _Tp
643
	value_or(_Up&& __u) const&
644
	{
645
	  static_assert(__and_,
646
			       is_convertible<_Up&&, _Tp>>(),
647
			"Cannot return value");
648
 
649
	  return this->_M_is_engaged()
650
	    ? this->_M_get()
651
	    : static_cast<_Tp>(std::forward<_Up>(__u));
652
	}
653
 
654
      template
655
	_Tp
656
	value_or(_Up&& __u) &&
657
	{
658
	  static_assert(__and_,
659
			       is_convertible<_Up&&, _Tp>>(),
660
			"Cannot return value" );
661
 
662
	  return this->_M_is_engaged()
663
	    ? std::move(this->_M_get())
664
	    : static_cast<_Tp>(std::forward<_Up>(__u));
665
	}
666
    };
667
 
668
  // [X.Y.8] Comparisons between optional values.
669
  template
670
    constexpr bool
671
    operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
672
    {
673
      return static_cast(__lhs) == static_cast(__rhs)
674
	     && (!__lhs || *__lhs == *__rhs);
675
    }
676
 
677
  template
678
    constexpr bool
679
    operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
680
    { return !(__lhs == __rhs); }
681
 
682
  template
683
    constexpr bool
684
    operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
685
    {
686
      return static_cast(__rhs) && (!__lhs || *__lhs < *__rhs);
687
    }
688
 
689
  template
690
    constexpr bool
691
    operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
692
    { return __rhs < __lhs; }
693
 
694
  template
695
    constexpr bool
696
    operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
697
    { return !(__rhs < __lhs); }
698
 
699
  template
700
    constexpr bool
701
    operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
702
    { return !(__lhs < __rhs); }
703
 
704
  // [X.Y.9] Comparisons with nullopt.
705
  template
706
    constexpr bool
707
    operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
708
    { return !__lhs; }
709
 
710
  template
711
    constexpr bool
712
    operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
713
    { return !__rhs; }
714
 
715
  template
716
    constexpr bool
717
    operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
718
    { return static_cast(__lhs); }
719
 
720
  template
721
    constexpr bool
722
    operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
723
    { return static_cast(__rhs); }
724
 
725
  template
726
    constexpr bool
727
    operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
728
    { return false; }
729
 
730
  template
731
    constexpr bool
732
    operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
733
    { return static_cast(__rhs); }
734
 
735
  template
736
    constexpr bool
737
    operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
738
    { return static_cast(__lhs); }
739
 
740
  template
741
    constexpr bool
742
    operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
743
    { return false; }
744
 
745
  template
746
    constexpr bool
747
    operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
748
    { return !__lhs; }
749
 
750
  template
751
    constexpr bool
752
    operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
753
    { return true; }
754
 
755
  template
756
    constexpr bool
757
    operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
758
    { return true; }
759
 
760
  template
761
    constexpr bool
762
    operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
763
    { return !__rhs; }
764
 
765
  // [X.Y.10] Comparisons with value type.
766
  template
767
    constexpr bool
768
    operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
769
    { return __lhs && *__lhs == __rhs; }
770
 
771
  template
772
    constexpr bool
773
    operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
774
    { return __rhs && __lhs == *__rhs; }
775
 
776
  template
777
    constexpr bool
778
    operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
779
    { return !__lhs || !(*__lhs == __rhs); }
780
 
781
  template
782
    constexpr bool
783
    operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
784
    { return !__rhs || !(__lhs == *__rhs); }
785
 
786
  template
787
    constexpr bool
788
    operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
789
    { return !__lhs || *__lhs < __rhs; }
790
 
791
  template
792
    constexpr bool
793
    operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
794
    { return __rhs && __lhs < *__rhs; }
795
 
796
  template
797
    constexpr bool
798
    operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
799
    { return __lhs && __rhs < *__lhs; }
800
 
801
  template
802
    constexpr bool
803
    operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
804
    { return !__rhs || *__rhs < __lhs; }
805
 
806
  template
807
    constexpr bool
808
    operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
809
    { return !__lhs || !(__rhs < *__lhs); }
810
 
811
  template
812
    constexpr bool
813
    operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
814
    { return __rhs && !(*__rhs < __lhs); }
815
 
816
  template
817
    constexpr bool
818
    operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
819
    { return __lhs && !(*__lhs < __rhs); }
820
 
821
  template
822
    constexpr bool
823
    operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
824
    { return !__rhs || !(__lhs < *__rhs); }
825
 
826
  // [X.Y.11]
827
  template
828
    inline void
829
    swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
830
    noexcept(noexcept(__lhs.swap(__rhs)))
831
    { __lhs.swap(__rhs); }
832
 
833
  template
834
    constexpr optional>
835
    make_optional(_Tp&& __t)
836
    { return optional> { std::forward<_Tp>(__t) }; }
837
 
838
  // @} group optional
839
_GLIBCXX_END_NAMESPACE_VERSION
840
} // namespace fundamentals_v1
841
}
842
 
843
  // [X.Y.12]
844
  template
845
    struct hash>
846
    {
847
      using result_type = size_t;
848
      using argument_type = experimental::optional<_Tp>;
849
 
850
      size_t
851
      operator()(const experimental::optional<_Tp>& __t) const
852
      noexcept(noexcept(hash<_Tp> {}(*__t)))
853
      {
854
        // We pick an arbitrary hash for disengaged optionals which hopefully
855
        // usual values of _Tp won't typically hash to.
856
        constexpr size_t __magic_disengaged_hash = static_cast(-3333);
857
        return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
858
      }
859
    };
860
}
861
 
862
#endif // C++14
863
 
864
#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL