Bug Summary

File:librecad/src/ui/dock_widgets/property_sheet/metaentity/entities/lc_propertyprovider_utils.h
Warning:line 202, column 9
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lc_propertiesprovider_line.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/runner/work/LibreCAD/LibreCAD/librecad/src -fcoverage-compilation-dir=/home/runner/work/LibreCAD/LibreCAD/librecad/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -D _REENTRANT -D DWGSUPPORT -D MUPARSER_STATIC -D LC_WITH_OPENTYPE=0 -D QC_APPDIR=librecad -D LC_VERSION=2.2.2_alpha1-853-ge2a8c2931 -D LC_PRERELEASE=true; -D QT_NO_DEBUG -D QT_SVG_LIB -D QT_PRINTSUPPORT_LIB -D QT_WIDGETS_LIB -D QT_GUI_LIB -D QT_NETWORK_LIB -D QT_CORE_LIB -I . -I /usr/include -I ../../libraries/lciconengine -I ../../libraries/libdxfrw/src -I ../../libraries/libdxfrw/src/intern -I ../../libraries/jwwlib/src -I ../../libraries/shapelib/src -I ../../libraries/qtbidi -I cmd -I lib/actions -I lib/actions/visual_snap -I lib/actions/options -I lib/creation -I lib/debug -I lib/engine -I lib/engine/document -I lib/engine/document/blocks -I lib/engine/document/container -I lib/engine/document/dimstyles -I lib/engine/document/entities -I lib/engine/document/entities/support -I lib/engine/document/fonts -I lib/engine/document/io -I lib/engine/document/layers -I lib/engine/document/linetypes -I lib/engine/document/patterns -I lib/engine/document/selection -I lib/engine/document/textstyles -I lib/engine/document/ucs -I lib/engine/document/variables -I lib/engine/document/views -I lib/engine/clipboard -I lib/engine/overlays -I lib/engine/overlays/angles_base -I lib/engine/overlays/highlight -I lib/engine/overlays/preview -I lib/engine/overlays/references -I lib/engine/overlays/crosshair -I lib/engine/overlays/info_cursor -I lib/engine/overlays/overlay_box -I lib/engine/overlays/ucs_mark -I lib/engine/undo -I lib/engine/utils -I lib/engine/settings -I lib/fileio -I lib/filters -I lib/generators -I lib/generators/makercamsvg -I lib/generators/layers -I lib/generators/image -I lib/gui -I lib/gui/grid -I lib/gui/render -I lib/gui/render/headless -I lib/gui/render/widget -I lib/information -I lib/math -I lib/modification -I lib/selection -I lib/selection/metaentity -I lib/selection/metaentity/entities -I lib/printing -I lib/properties -I actions -I actions/dock_widgets -I actions/dock_widgets/block -I actions/dock_widgets/entity_info -I actions/dock_widgets/layer -I actions/dock_widgets/library -I actions/dock_widgets/ucs_list -I actions/drawing -I actions/drawing/draw -I actions/drawing/draw/arc -I actions/drawing/draw/circle -I actions/drawing/draw/curve -I actions/drawing/draw/spline -I actions/drawing/draw/dimensions -I actions/drawing/draw/ellipse -I actions/drawing/draw/hatch -I actions/drawing/draw/image -I actions/drawing/draw/line -I actions/drawing/draw/point -I actions/drawing/draw/rect -I actions/drawing/draw/polygon -I actions/drawing/draw/misc -I actions/drawing/draw/line/shapes -I actions/drawing/draw/line/misc -I actions/drawing/draw/line/shapes/rect -I actions/drawing/draw/line/shapes/polygon -I actions/drawing/draw/polyline -I actions/drawing/draw/text -I actions/drawing/edit -I actions/drawing/info -I actions/drawing/pick -I actions/drawing/modify -I actions/drawing/pen -I actions/drawing/rel_zero -I actions/drawing/selection -I actions/drawing/snap -I actions/drawing/zoom -I actions/file -I actions/options -I actions/print_preview -I ui -I ui/action_options -I ui/action_options/circle -I ui/action_options/curve -I ui/action_options/spline -I ui/action_options/dimensions -I ui/action_options/edit -I ui/action_options/image -I ui/action_options/info -I ui/action_options/insert -I ui/action_options/line -I ui/action_options/rect -I ui/action_options/polygon -I ui/action_options/misc -I ui/action_options/modify -I ui/action_options/ellipse -I ui/action_options/other -I ui/action_options/polyline -I ui/action_options/point -I ui/action_options/print_preview -I ui/action_options/selection -I ui/action_options/snap -I ui/action_options/text -I ui/actions -I ui/components -I ui/components/relative_position_assistant -I ui/components/comboboxes -I ui/components/containers -I ui/components/creators -I ui/components/layouts -I ui/components/pen -I ui/components/status_bar -I ui/components/toolbars -I ui/components/utils -I ui/dialogs -I ui/dialogs/actions -I ui/dialogs/actions/modify -I ui/dialogs/actions/quick_selection -I ui/dialogs/modify -I ui/dialogs/entity -I ui/dialogs/creators -I ui/dialogs/file -I ui/dialogs/file/export -I ui/dialogs/file/export/layers -I ui/dialogs/file/export/image -I ui/dialogs/file/export/makercam -I ui/dialogs/main -I ui/dialogs/settings -I ui/dialogs/settings/dimstyles -I ui/dialogs/settings/dimstyles/dimstyle_manager -I ui/dialogs/settings/dimstyles/dimstyle_manager/support -I ui/dialogs/settings/options_device -I ui/dialogs/settings/options_drawing -I ui/dialogs/settings/options_general -I ui/dialogs/settings/options_widget -I ui/dialogs/settings/shortcuts -I ui/dock_widgets -I ui/dock_widgets/block_widget -I ui/dock_widgets/command_line -I ui/dock_widgets/entity_info -I ui/dock_widgets/layer_widget -I ui/dock_widgets/layers_tree -I ui/dock_widgets/library_widget -I ui/dock_widgets/pen_palette -I ui/dock_widgets/pen_wizard -I ui/dock_widgets/property_sheet -I ui/dock_widgets/property_sheet/lib -I ui/dock_widgets/property_sheet/lib/properties -I ui/dock_widgets/property_sheet/lib/view -I ui/dock_widgets/property_sheet/lib/view/edit -I ui/dock_widgets/property_sheet/lib/widgets -I ui/dock_widgets/property_sheet/lib/widgets/sheet -I ui/dock_widgets/property_sheet/metaentity -I ui/dock_widgets/property_sheet/metaentity/entities -I ui/dock_widgets/property_sheet/metaentity/entities/document -I ui/dock_widgets/property_sheet/properties -I ui/dock_widgets/property_sheet/properties/action -I ui/dock_widgets/property_sheet/properties/bool -I ui/dock_widgets/property_sheet/properties/color -I ui/dock_widgets/property_sheet/properties/double -I ui/dock_widgets/property_sheet/properties/enum -I ui/dock_widgets/property_sheet/properties/int -I ui/dock_widgets/property_sheet/properties/layer -I ui/dock_widgets/property_sheet/properties/linetype -I ui/dock_widgets/property_sheet/properties/linewidth -I ui/dock_widgets/property_sheet/properties/rect -I ui/dock_widgets/property_sheet/properties/rsvector -I ui/dock_widgets/property_sheet/properties/string -I ui/dock_widgets/views_list -I ui/dock_widgets/ucs_list -I ui/dock_widgets/workspaces -I ui/dock_widgets/cad -I ui/main -I ui/main/init -I ui/main/persistence -I ui/main/release_check -I ui/main/support -I ui/main/fontviewer -I ui/main/workspaces -I ui/view -I main -I main/console_dxf2pdf -I test -I plugins -I ../res -I ../res/arrows -I ../res/controls -I ../res/dxf -I ../res/gdt -I ../res/icons -I ../res/images -I ../../../Qt/6.9.0/gcc_64/include -I ../../../Qt/6.9.0/gcc_64/include/QtSvg -I ../../../Qt/6.9.0/gcc_64/include/QtPrintSupport -I ../../../Qt/6.9.0/gcc_64/include/QtWidgets -I ../../../Qt/6.9.0/gcc_64/include/QtGui -I ../../../Qt/6.9.0/gcc_64/include/QtNetwork -I ../../../Qt/6.9.0/gcc_64/include/QtCore -I ../../generated/librecad/moc -I ../../generated/librecad/ui -I ../../../Qt/6.9.0/gcc_64/mkspecs/linux-g++ -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/x86_64-linux-gnu/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu++1z -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/runner/work/LibreCAD/LibreCAD/out/2026-11-06-031751-4837-1 -x c++ ui/dock_widgets/property_sheet/metaentity/entities/lc_propertiesprovider_line.cpp

ui/dock_widgets/property_sheet/metaentity/entities/lc_propertiesprovider_line.cpp

→
1/*
2 * ********************************************************************************
3 * This file is part of the LibreCAD project, a 2D CAD program
4 *
5 * Copyright (C) 2025 LibreCAD.org
6 * Copyright (C) 2025 sand1024
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * ********************************************************************************
22 */
23
24#include "lc_propertiesprovider_line.h"
25
26#include "lc_convert.h"
27#include "lc_property_action.h"
28#include "lc_propertyprovider_utils.h"
29#include "rs_line.h"
30
31
32void LC_PropertiesProviderLine::doCreateEntitySpecificProperties(LC_PropertyContainer* cont, const QList<RS_Entity*>& list) {
33 const auto contGeometry = createGeometrySection(cont);
34
35 addVector<RS_Line>({"start", tr("Start"), tr("Start point of line")}, [](const RS_Line* e) -> RS_Vector {
36 return e->getStartpoint();
37 }, [](const RS_Vector& v, RS_Line* l) -> void {
38 l->setStartpoint(v);
39 }, list, contGeometry);
40
41 addVector<RS_Line>({"end", tr("End"), tr("End point of line")}, [](const RS_Line* line) -> RS_Vector {
42 return line->getEndpoint();
43 }, [](const RS_Vector& v, RS_Line* l) -> void {
44 l->setEndpoint(v);
45 }, list, contGeometry);
46}
47
48void LC_PropertiesProviderLine::doCreateCalculatedProperties(LC_PropertyContainer* cont, const QList<RS_Entity*>& list) {
49 addReadOnlyString<RS_Line>({"length", tr("Length"), tr("Length of line")}, [this](const RS_Line* e) -> QString {
50 const double len = e->getLength();
51 QString value = formatLinear(len);
52 return value;
53 }, list, cont);
54
55 addReadOnlyString<RS_Line>({"angle1", tr("Angle 1"), tr("Angle from 0.0 to first point of line")}, [this](const RS_Line* e) -> QString {
56 const double wcsAngleRad = e->getAngle1();
57 QString value = formatWCSAngleDegrees(wcsAngleRad);
58 return value;
59 }, list, cont);
60
61 addReadOnlyString<RS_Line>({"angle2", tr("Angle 2"), tr("Angle from 0.0 to second point of line")},
62 [this](const RS_Line* e) -> QString {
63 const double wcsAngleRad = e->getAngle2();
64 QString value = formatWCSAngleDegrees(wcsAngleRad);
65 return value;
66 }, list, cont);
67
68 // addReadOnlyString<RS_Line>({"inclination", tr("Inclination"), tr("Angle of the line inclination to x-axis")},
69 // [this](const RS_Line* e) -> QString {
70 // const double wcsAngleRad = RS_Math::correctAngle0ToPi(e->getAngle1());
71 // QString value = formatWCSAngleDegrees(wcsAngleRad);
72 // return value;
73 // }, list, container);
74
75 const auto graphicViewport = m_actionContext->getViewport();
76 if (graphicViewport != nullptr) {
77 addVector<RS_Line>({"delta", tr("Delta"), tr("Distance between start and end point")}, [this](const RS_Line* line) -> RS_Vector {
78 const auto deltaVectorWCS = line->getEndpoint() - line->getStartpoint();
79 const auto viewport = m_actionContext->getViewport();
80 if (viewport == nullptr) {
81 return deltaVectorWCS;
82 }
83 const auto ucsDelta = viewport->toUCSDelta(deltaVectorWCS);
84 return ucsDelta;
85 }, nullptr, list, cont);
86 }
87
88 addVector<RS_Line>({"middle", tr("Middle Point"), tr("Middle point of line")}, [](const RS_Line* e) -> RS_Vector {
89 return e->getMiddlePoint();
90 }, nullptr, list, cont);
91}
92
93void LC_PropertiesProviderLine::doCreateSingleEntityCommands(LC_PropertyContainer* container, RS_Entity* ent) {
94 const auto line = static_cast<RS_Line*>(ent);
95
96 const std::list<CommandLinkInfo> commands1 = {
97 {
98 tr("Length and lines join"),
99 {RS2::ActionModifyTrimAmount, tr("Lengthen"), tr("Lengthen or shorten the line by a given distance")},
100 {RS2::ActionModifyLineJoin, tr("Line Join"), tr("Join two lines")}
101 },
102 {
103 tr("Trimming two lines"),
104 {RS2::ActionModifyTrim, tr("Trim"), tr("Trim line by limiting entity")},
105 {RS2::ActionModifyTrim2, tr("Trim Two"), tr("Trim two lines")}
106 },
107 {
108 tr("Cutting and gap"),
109 {RS2::ActionModifyCut, tr("Divide"), tr("Divide line")},
110 {RS2::ActionModifyLineGap, tr("Line Gap"), tr("Break the line by gap")}
111 }
112 };
113
114 createEntityContextCommands<RS_Line>(commands1, container, line, "lineCommands1");
115
116 auto clickHandler = [this]([[maybe_unused]] RS_Line* entity, const int linkIndex) {
117 switch (linkIndex) {
118 case 0: {
119 m_actionContext->saveContextMenuActionContext(entity, entity->getStartpoint(), false);
120 m_actionContext->setCurrentAction(RS2::ActionDrawArcTangential, nullptr);
121 break;
122 }
123 case 1: {
124 m_actionContext->saveContextMenuActionContext(entity, entity->getEndpoint(), false);
125 m_actionContext->setCurrentAction(RS2::ActionDrawArcTangential, nullptr);
126 break;
127 }
128 default:
129 break;
130 }
131 };
132 LC_PropertyProviderUtils::createSingleEntityCommand<RS_Line>(container, "lineActTanStart", tr("Tangental Arc (start)"),
133 tr("Create tangental arc in start point"),
134 tr("Tangental Arc (end)"), tr("Create tangental arc in end point"),line,
135 clickHandler, tr("Creation of tangental arc"));
136
137 const std::list<CommandLinkInfo> commands2 = {
138 {
139 tr("Creation of parallels or bisector lines"),
140 {RS2::ActionDrawLineParallelThrough, tr("Parallel"), tr("Create parallel line through point")},
141 {RS2::ActionDrawLineBisector, tr("Bisector"), tr("Create bisector between lines")}
142 },
143 {
144 tr("Creating orthogonal or relative angle lines"),
145 {RS2::ActionDrawLineOrthogonal, tr("Orthogonal"), tr("Create line orthogonal to this line")},
146 {RS2::ActionDrawLineRelAngle, tr("Relative Angle"), tr("Create line with relative angle to this line")}
147 },
148 {
149 tr("Creation of line from point or tangental orthogonal"),
150 {RS2::ActionDrawLineFromPointToLine, tr("Line from Point"), tr("Create line from point to this line")},
151 {RS2::ActionDrawLineOrthTan, tr("Tangent Ort"), tr("Create orthogonal line that is tangental to other entity")}
152 },
153 {
154 tr("Creation of circle tangental to line"),
155 {RS2::ActionDrawCircleTangental1Entity2Points, tr("Tangential Circle (2 P)"), tr("Create circle tangental by 2 points")},
156 {RS2::ActionDrawCircleTangental2Entities1Point, tr("Tangential Circle (2 E, 1 P)"), tr("Create circle tangental by 2 entities and 1 point")}
157 },
158 {
159 tr("Creation of circle tangental to line"),
160 {RS2::ActionDrawCircleTan3Entities, tr("Tangential Circle (3 E)"), tr("Create circle tangental to 3 entities")},
161 {RS2::ActionDrawCircleTan2EntitiesRadius, tr("Tangential Circle (2 E, R)"), tr("Create circle tangental by 2 entities and radius")}
162 },
163 {
164 tr("Creation of ellipse or bounding box"),
165 {RS2::ActionDrawEllipseInscribe, tr("Ellipse inscribed"), tr("Create ellipse inscribed")},
166 {RS2::ActionDrawBoundingBox, tr("Bounding box"), tr("Create bounding box for line")}
167 },
168 {
169 tr("Modification of line with bevel or fillet"),
170 {RS2::ActionModifyBevel, tr("Bevel"), tr("Create a bevel")},
171 {RS2::ActionModifyRound, tr("Round"), tr("Create rounding between line and other entity")}
172 },
173 {
174 tr("Dividing line"),
175 {RS2::ActionDrawSliceDivideLine, tr("Slice/Divide"), tr("Slice or divide a line")},
176 {RS2::ActionModifyBreakDivide, tr("Break/Divide"), tr("Break or divide the line by intersection points")}
177 },
178 {tr("Center line"),
179 {RS2::ActionDrawCenterLine, tr("Centerline"), tr("Create center line between two lines")},
180 {RS2::ActionDrawLineRadiant, tr("Radiant"), tr("Create radiant line from center point")},
181 },
182 {
183 tr("Creation of dimension, aligned or linear"),
184 {RS2::ActionDimAligned, tr("Dim Aligned"), tr("Create aligned dimension for line")},
185 {RS2::ActionDimLinear, tr("Dim Linear"), tr("Create linear dimension for line")}
186 },
187 {
188 tr("Creation of dimension, angular or ordinate"),
189 {RS2::ActionDimAngular, tr("Dim Angular"), tr("Create angular dimension for line")},
190 {RS2::ActionDimOrdinate, tr("Dim Ordinate"), tr("Create ordinate dimension for line")}
191 }
192 };
193
194 createEntityContextCommands<RS_Line>(commands2, container, line, "lineCommands2");
195}
196
197void LC_PropertiesProviderLine::doCreateSelectedSetCommands(LC_PropertyContainer* propertyContainer, const QList<RS_Entity*>& list) {
198 LC_EntityTypePropertiesProvider::doCreateSelectedSetCommands(propertyContainer, list);
199
200 const std::list<CommandLinkInfo> commands = {
201 {
202 tr("Reverting direction"),
203 {RS2::ActionModifyRevertDirection, tr("Revert direction"), tr("Change direction of line by swapping start and end points")}
204 }
205 };
206 createEntityContextCommands<RS_Line>(commands, propertyContainer, nullptr, "arcMultiCommands", false);
1
Calling 'LC_EntityTypePropertiesProvider::createEntityContextCommands'
207}

←

/usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/bits/stl_list.h

→
1// List implementation -*- C++ -*-
2
3// Copyright (C) 2001-2025 Free Software Foundation, Inc.
4// Copyright The GNU Toolchain Authors.
5//
6// This file is part of the GNU ISO C++ Library. This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24// <http://www.gnu.org/licenses/>.
25
26/*
27 *
28 * Copyright (c) 1994
29 * Hewlett-Packard Company
30 *
31 * Permission to use, copy, modify, distribute and sell this software
32 * and its documentation for any purpose is hereby granted without fee,
33 * provided that the above copyright notice appear in all copies and
34 * that both that copyright notice and this permission notice appear
35 * in supporting documentation. Hewlett-Packard Company makes no
36 * representations about the suitability of this software for any
37 * purpose. It is provided "as is" without express or implied warranty.
38 *
39 *
40 * Copyright (c) 1996,1997
41 * Silicon Graphics Computer Systems, Inc.
42 *
43 * Permission to use, copy, modify, distribute and sell this software
44 * and its documentation for any purpose is hereby granted without fee,
45 * provided that the above copyright notice appear in all copies and
46 * that both that copyright notice and this permission notice appear
47 * in supporting documentation. Silicon Graphics makes no
48 * representations about the suitability of this software for any
49 * purpose. It is provided "as is" without express or implied warranty.
50 */
51
52/** @file bits/stl_list.h
53 * This is an internal header file, included by other library headers.
54 * Do not attempt to use it directly. @headername{list}
55 */
56
57#ifndef _STL_LIST_H1
58#define _STL_LIST_H1 1
59
60#include <bits/concept_check.h>
61#include <ext/alloc_traits.h>
62#include <debug/assertions.h>
63#if __cplusplus201703L >= 201103L
64#include <initializer_list>
65#include <bits/allocated_ptr.h>
66#include <bits/ptr_traits.h>
67#include <ext/aligned_buffer.h>
68#endif
69#if __glibcxx_containers_ranges // C++ >= 23
70# include <bits/ranges_base.h> // ranges::begin, ranges::distance etc.
71# include <bits/ranges_util.h> // ranges::subrange
72#endif
73
74#if __cplusplus201703L < 201103L
75# undef _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
76# define _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1 0
77#elif ! defined _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
78# define _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1 1
79#endif
80
81namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
82{
83_GLIBCXX_BEGIN_NAMESPACE_VERSION
84
85 namespace __detail
86 {
87 // Supporting structures are split into common and templated
88 // types; the latter publicly inherits from the former in an
89 // effort to reduce code duplication. This results in some
90 // "needless" static_cast'ing later on, but it's all safe
91 // downcasting.
92
93 /// Common part of a node in the %list.
94 struct _List_node_base
95 {
96 typedef _List_node_base* _Base_ptr;
97
98 _List_node_base* _M_next;
99 _List_node_base* _M_prev;
100
101 static void
102 swap(_List_node_base& __x, _List_node_base& __y) _GLIBCXX_USE_NOEXCEPTnoexcept;
103
104 void
105 _M_transfer(_List_node_base* const __first,
106 _List_node_base* const __last) _GLIBCXX_USE_NOEXCEPTnoexcept;
107
108 void
109 _M_reverse() _GLIBCXX_USE_NOEXCEPTnoexcept;
110
111 void
112 _M_hook(_List_node_base* const __position) _GLIBCXX_USE_NOEXCEPTnoexcept;
113
114 void
115 _M_unhook() _GLIBCXX_USE_NOEXCEPTnoexcept;
116
117 _List_node_base* _M_base() { return this; }
118 const _List_node_base* _M_base() const { return this; }
119 };
120
121 struct _List_size
122 {
123#if _GLIBCXX_USE_CXX11_ABI1
124 // Store the size here so that std::list::size() is fast.
125 size_t _M_size;
126#endif
127 };
128
129 /// The %list node header.
130 struct _List_node_header : public _List_node_base, _List_size
131 {
132 _List_node_header() _GLIBCXX_NOEXCEPTnoexcept
133 { _M_init(); }
134
135#if __cplusplus201703L >= 201103L
136 _List_node_header(_List_node_header&& __x) noexcept
137 : _List_node_base(__x), _List_size(__x)
138 {
139 if (__x._M_base()->_M_next == __x._M_base())
140 this->_M_next = this->_M_prev = this;
141 else
142 {
143 this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base();
144 __x._M_init();
145 }
146 }
147
148 void
149 _M_move_nodes(_List_node_header&& __x)
150 {
151 _List_node_base* const __xnode = __x._M_base();
152 if (__xnode->_M_next == __xnode)
153 _M_init();
154 else
155 {
156 _List_node_base* const __node = this->_M_base();
157 __node->_M_next = __xnode->_M_next;
158 __node->_M_prev = __xnode->_M_prev;
159 __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
160 _List_size::operator=(__x);
161 __x._M_init();
162 }
163 }
164#endif
165
166 void
167 _M_init() _GLIBCXX_NOEXCEPTnoexcept
168 {
169 this->_M_next = this->_M_prev = this;
170 _List_size::operator=(_List_size());
171 }
172
173 using _List_node_base::_M_base;
174#if ! _GLIBCXX_INLINE_VERSION0
175 _List_node_base* _M_base() { return this; } // XXX GLIBCXX_ABI Deprecated
176#endif
177 };
178
179 } // namespace detail
180
181#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
182_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
183_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
184 template<typename _Tp, typename _Allocator> class list;
185_GLIBCXX_END_NAMESPACE_CXX11}
186_GLIBCXX_END_NAMESPACE_CONTAINER
187
188namespace __list
189{
190 // The base class for a list node. Contains the pointers connecting nodes.
191 template<typename _VoidPtr>
192 struct _Node_base
193 {
194 using _Base_ptr = __ptr_rebind<_VoidPtr, _Node_base>;
195 _Base_ptr _M_next;
196 _Base_ptr _M_prev;
197
198 static void
199 swap(_Node_base& __x, _Node_base& __y) noexcept;
200
201 void
202 _M_transfer(_Base_ptr const __first, _Base_ptr const __last) noexcept;
203
204 void
205 _M_hook(_Base_ptr const __position) noexcept
206 {
207 auto __self = this->_M_base();
208 this->_M_next = __position;
209 this->_M_prev = __position->_M_prev;
210 __position->_M_prev->_M_next = __self;
211 __position->_M_prev = __self;
212 }
213
214 void
215 _M_unhook() noexcept
216 {
217 auto const __next_node = this->_M_next;
218 auto const __prev_node = this->_M_prev;
219 __prev_node->_M_next = __next_node;
220 __next_node->_M_prev = __prev_node;
221 }
222
223 // This is not const-correct, but it's only used in a const access path
224 // by std::list::empty(), where it doesn't escape, and by
225 // std::list::end() const, where the pointer is used to initialize a
226 // const_iterator and so constness is restored.
227 // The standard allows pointer_to to be potentially-throwing,
228 // but we have to assume it doesn't throw to implement std::list.
229 _Base_ptr
230 _M_base() const noexcept
231 {
232 return pointer_traits<_Base_ptr>::
233 pointer_to(const_cast<_Node_base&>(*this));
234 }
235 };
236
237 using ::std::__detail::_List_size;
238
239 // The special sentinel node contained by a std::list.
240 // begin()->_M_node->_M_prev and end()->_M_node point to this header.
241 // This is not a complete node, as it doesn't contain a value.
242 template<typename _VoidPtr>
243 struct _Node_header
244 : public _Node_base<_VoidPtr>, _List_size
245 {
246 _Node_header() noexcept
247 { _M_init(); }
248
249 _Node_header(_Node_header&& __x) noexcept
250 : _Node_base<_VoidPtr>(__x), _List_size(__x)
251 {
252 if (__x._M_base()->_M_next == __x._M_base())
253 this->_M_next = this->_M_prev = this->_M_base();
254 else
255 {
256 this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base();
257 __x._M_init();
258 }
259 }
260
261 void
262 _M_move_nodes(_Node_header&& __x) noexcept
263 {
264 auto const __xnode = __x._M_base();
265 if (__xnode->_M_next == __xnode)
266 _M_init();
267 else
268 {
269 auto const __node = this->_M_base();
270 __node->_M_next = __xnode->_M_next;
271 __node->_M_prev = __xnode->_M_prev;
272 __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
273 _List_size::operator=(__x);
274 __x._M_init();
275 }
276 }
277
278 void
279 _M_init() noexcept
280 {
281 this->_M_next = this->_M_prev = this->_M_base();
282 _List_size::operator=(_List_size());
283 }
284
285 void _M_reverse() noexcept;
286 };
287
288 // The node type used for allocators with fancy pointers.
289 template<typename _ValPtr>
290 struct _Node : public __list::_Node_base<__ptr_rebind<_ValPtr, void>>
291 {
292 using value_type = typename pointer_traits<_ValPtr>::element_type;
293 using _Node_ptr = __ptr_rebind<_ValPtr, _Node>;
294
295 _Node() noexcept { }
296 ~_Node() { }
297 _Node(_Node&&) = delete;
298
299 union _Uninit_storage
300 {
301 _Uninit_storage() noexcept { }
302 ~_Uninit_storage() { }
303
304 value_type _M_data;
305 };
306 _Uninit_storage _M_u;
307
308 value_type*
309 _M_valptr() noexcept { return std::__addressof(_M_u._M_data); }
310
311 value_type const*
312 _M_valptr() const noexcept { return std::__addressof(_M_u._M_data); }
313
314 _Node_ptr
315 _M_node_ptr()
316 { return pointer_traits<_Node_ptr>::pointer_to(*this); }
317 };
318
319 template<bool _Const, typename _Ptr> class _Iterator;
320
321 template<bool _Const, typename _Ptr>
322 class _Iterator
323 {
324 using _Node = __list::_Node<_Ptr>;
325 using _Base_ptr
326 = typename __list::_Node_base<__ptr_rebind<_Ptr, void>>::_Base_ptr;
327
328 template<typename _Tp>
329 using __maybe_const = __conditional_t<_Const, const _Tp, _Tp>;
330
331 public:
332 using value_type = typename pointer_traits<_Ptr>::element_type;
333 using difference_type = ptrdiff_t;
334 using iterator_category = bidirectional_iterator_tag;
335 using pointer = __maybe_const<value_type>*;
336 using reference = __maybe_const<value_type>&;
337
338 constexpr _Iterator() noexcept : _M_node() { }
339
340 _Iterator(const _Iterator&) = default;
341 _Iterator& operator=(const _Iterator&) = default;
342
343#ifdef __glibcxx_concepts
344 constexpr
345 _Iterator(const _Iterator<false, _Ptr>& __i) requires _Const
346#else
347 template<bool _OtherConst,
348 typename = __enable_if_t<_Const && !_OtherConst>>
349 constexpr
350 _Iterator(const _Iterator<_OtherConst, _Ptr>& __i)
351#endif
352 : _M_node(__i._M_node) { }
353
354 constexpr explicit
355 _Iterator(_Base_ptr __x) noexcept
356 : _M_node(__x) { }
357
358 // Must downcast from _Node_base to _Node to get to value.
359 [[__nodiscard__]]
360 constexpr reference
361 operator*() const noexcept
362 { return static_cast<_Node&>(*_M_node)._M_u._M_data; }
363
364 [[__nodiscard__]]
365 constexpr pointer
366 operator->() const noexcept
367 { return std::__addressof(operator*()); }
368
369 _GLIBCXX14_CONSTEXPRconstexpr _Iterator&
370 operator++() noexcept
371 {
372 _M_node = _M_node->_M_next;
373 return *this;
374 }
375
376 _GLIBCXX14_CONSTEXPRconstexpr _Iterator
377 operator++(int) noexcept
378 {
379 auto __tmp = *this;
380 _M_node = _M_node->_M_next;
381 return __tmp;
382 }
383
384 _GLIBCXX14_CONSTEXPRconstexpr _Iterator&
385 operator--() noexcept
386 {
387 _M_node = _M_node->_M_prev;
388 return *this;
389 }
390
391 _GLIBCXX14_CONSTEXPRconstexpr _Iterator
392 operator--(int) noexcept
393 {
394 auto __tmp = *this;
395 _M_node = _M_node->_M_prev;
396 return __tmp;
397 }
398
399 [[__nodiscard__]]
400 friend constexpr bool
401 operator==(const _Iterator& __x, const _Iterator& __y) noexcept
402 { return __x._M_node == __y._M_node; }
403
404#if __cpp_impl_three_way_comparison < 201907L
405 [[__nodiscard__]]
406 friend constexpr bool
407 operator!=(const _Iterator& __x, const _Iterator& __y) noexcept
408 { return __x._M_node != __y._M_node; }
409#endif
410
411 private:
412 template<typename _Tp, typename _Allocator>
413 friend class _GLIBCXX_STD_Cstd::list;
414
415 friend _Iterator<!_Const, _Ptr>;
416
417 constexpr _Iterator<false, _Ptr>
418 _M_const_cast() const noexcept
419 { return _Iterator<false, _Ptr>(_M_node); }
420
421 _Base_ptr _M_node;
422 };
423} // namespace __list
424#endif // USE_ALLOC_PTR_FOR_LIST
425
426_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
427 template<typename _Tp> struct _List_node;
428 template<typename _Tp> struct _List_iterator;
429 template<typename _Tp> struct _List_const_iterator;
430_GLIBCXX_END_NAMESPACE_CONTAINER
431
432namespace __list
433{
434 // Determine the node and iterator types used by std::list.
435 template<typename _Tp, typename _Ptr>
436 struct _Node_traits;
437
438#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1 <= 9000
439 // Specialization for the simple case where the allocator's pointer type
440 // is the same type as value_type*.
441 // For ABI compatibility we can't change the types used for this case.
442 template<typename _Tp>
443 struct _Node_traits<_Tp, _Tp*>
444 {
445 typedef __detail::_List_node_base _Node_base;
446 typedef __detail::_List_node_header _Node_header;
447 typedef _GLIBCXX_STD_Cstd::_List_node<_Tp> _Node;
448 typedef _GLIBCXX_STD_Cstd::_List_iterator<_Tp> _Iterator;
449 typedef _GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> _Const_iterator;
450 };
451#endif
452
453#if ! _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
454 // Always use the T* specialization.
455 template<typename _Tp, typename _Ptr>
456 struct _Node_traits
457 : _Node_traits<_Tp, _Tp*>
458 { };
459#else
460 // Primary template used when the allocator uses fancy pointers.
461 template<typename _Tp, typename _Ptr>
462 struct _Node_traits
463 {
464 private:
465 using _VoidPtr = __ptr_rebind<_Ptr, void>;
466 using _ValPtr = __ptr_rebind<_Ptr, _Tp>;
467
468 public:
469 using _Node_base = __list::_Node_base<_VoidPtr>;
470 using _Node_header = __list::_Node_header<_VoidPtr>;
471 using _Node = __list::_Node<_ValPtr>;
472 using _Iterator = __list::_Iterator<false, _ValPtr>;
473 using _Const_iterator = __list::_Iterator<true, _ValPtr>;
474 };
475#endif // USE_ALLOC_PTR_FOR_LIST
476
477 // Used by std::list::sort to hold nodes being sorted.
478 template<typename _NodeBaseT>
479 struct _Scratch_list
480 : _NodeBaseT
481 {
482 typedef _NodeBaseT _Base;
483 typedef typename _Base::_Base_ptr _Base_ptr;
484
485 _Scratch_list() { this->_M_next = this->_M_prev = this->_M_base(); }
486
487 bool empty() const { return this->_M_next == this->_M_base(); }
488
489 void swap(_Base& __l) { _Base::swap(*this, __l); }
490
491 template<typename _Iter, typename _Cmp>
492 struct _Ptr_cmp
493 {
494 _Cmp _M_cmp;
495
496 bool
497 operator()(_Base_ptr __lhs, _Base_ptr __rhs) /* not const */
498 { return _M_cmp(*_Iter(__lhs), *_Iter(__rhs)); }
499 };
500
501 template<typename _Iter>
502 struct _Ptr_cmp<_Iter, void>
503 {
504 bool
505 operator()(_Base_ptr __lhs, _Base_ptr __rhs) const
506 { return *_Iter(__lhs) < *_Iter(__rhs); }
507 };
508
509 // Merge nodes from __x into *this. Both lists must be sorted wrt _Cmp.
510 template<typename _Cmp>
511 void
512 merge(_Base& __x, _Cmp __comp)
513 {
514 _Base_ptr __first1 = this->_M_next;
515 _Base_ptr const __last1 = this->_M_base();
516 _Base_ptr __first2 = __x._M_next;
517 _Base_ptr const __last2 = __x._M_base();
518
519 while (__first1 != __last1 && __first2 != __last2)
520 {
521 if (__comp(__first2, __first1))
522 {
523 _Base_ptr __next = __first2->_M_next;
524 __first1->_M_transfer(__first2, __next);
525 __first2 = __next;
526 }
527 else
528 __first1 = __first1->_M_next;
529 }
530 if (__first2 != __last2)
531 this->_M_transfer(__first2, __last2);
532 }
533
534 // Splice the node at __i into *this.
535 void _M_take_one(_Base_ptr __i)
536 { this->_M_transfer(__i, __i->_M_next); }
537
538 // Splice all nodes from *this after __i.
539 void _M_put_all(_Base_ptr __i)
540 {
541 if (!empty())
542 __i->_M_transfer(this->_M_next, this->_M_base());
543 }
544 };
545} // namespace __list
546
547_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
548
549 /// An actual node in the %list.
550 template<typename _Tp>
551 struct _List_node : public __detail::_List_node_base
552 {
553 typedef _List_node* _Node_ptr;
554
555#if __cplusplus201703L >= 201103L
556 __gnu_cxx::__aligned_membuf<_Tp> _M_storage;
557 _Tp* _M_valptr() { return _M_storage._M_ptr(); }
558 _Tp const* _M_valptr() const { return _M_storage._M_ptr(); }
559#else
560 _Tp _M_data;
561 _Tp* _M_valptr() { return std::__addressof(_M_data); }
562 _Tp const* _M_valptr() const { return std::__addressof(_M_data); }
563#endif
564
565 _Node_ptr _M_node_ptr() { return this; }
566 };
567
568 /**
569 * @brief A list::iterator.
570 *
571 * All the functions are op overloads.
572 */
573 template<typename _Tp>
574 struct _List_iterator
575 {
576 typedef _List_node<_Tp> _Node;
577
578 typedef ptrdiff_t difference_type;
579 typedef std::bidirectional_iterator_tag iterator_category;
580 typedef _Tp value_type;
581 typedef _Tp* pointer;
582 typedef _Tp& reference;
583
584 _List_iterator() _GLIBCXX_NOEXCEPTnoexcept
585 : _M_node() { }
586
587 explicit
588 _List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPTnoexcept
589 : _M_node(__x) { }
590
591 _List_iterator
592 _M_const_cast() const _GLIBCXX_NOEXCEPTnoexcept
593 { return *this; }
594
595 // Must downcast from _List_node_base to _List_node to get to value.
596 _GLIBCXX_NODISCARD[[__nodiscard__]]
597 reference
598 operator*() const _GLIBCXX_NOEXCEPTnoexcept
599 { return *static_cast<_Node*>(_M_node)->_M_valptr(); }
600
601 _GLIBCXX_NODISCARD[[__nodiscard__]]
602 pointer
603 operator->() const _GLIBCXX_NOEXCEPTnoexcept
604 { return static_cast<_Node*>(_M_node)->_M_valptr(); }
605
606 _List_iterator&
607 operator++() _GLIBCXX_NOEXCEPTnoexcept
608 {
609 _M_node = _M_node->_M_next;
610 return *this;
611 }
612
613 _List_iterator
614 operator++(int) _GLIBCXX_NOEXCEPTnoexcept
615 {
616 _List_iterator __tmp = *this;
617 _M_node = _M_node->_M_next;
618 return __tmp;
619 }
620
621 _List_iterator&
622 operator--() _GLIBCXX_NOEXCEPTnoexcept
623 {
624 _M_node = _M_node->_M_prev;
625 return *this;
626 }
627
628 _List_iterator
629 operator--(int) _GLIBCXX_NOEXCEPTnoexcept
630 {
631 _List_iterator __tmp = *this;
632 _M_node = _M_node->_M_prev;
633 return __tmp;
634 }
635
636 _GLIBCXX_NODISCARD[[__nodiscard__]]
637 friend bool
638 operator==(const _List_iterator& __x,
639 const _List_iterator& __y) _GLIBCXX_NOEXCEPTnoexcept
640 { return __x._M_node == __y._M_node; }
641
642#if __cpp_impl_three_way_comparison < 201907L
643 _GLIBCXX_NODISCARD[[__nodiscard__]]
644 friend bool
645 operator!=(const _List_iterator& __x,
646 const _List_iterator& __y) _GLIBCXX_NOEXCEPTnoexcept
647 { return __x._M_node != __y._M_node; }
648#endif
649
650 // The only member points to the %list element.
651 __detail::_List_node_base* _M_node;
652 };
653
654 /**
655 * @brief A list::const_iterator.
656 *
657 * All the functions are op overloads.
658 */
659 template<typename _Tp>
660 struct _List_const_iterator
661 {
662 typedef const _List_node<_Tp> _Node;
663 typedef _List_iterator<_Tp> iterator;
664
665 typedef ptrdiff_t difference_type;
666 typedef std::bidirectional_iterator_tag iterator_category;
667 typedef _Tp value_type;
668 typedef const _Tp* pointer;
669 typedef const _Tp& reference;
670
671 _List_const_iterator() _GLIBCXX_NOEXCEPTnoexcept
672 : _M_node() { }
673
674 explicit
675 _List_const_iterator(const __detail::_List_node_base* __x)
676 _GLIBCXX_NOEXCEPTnoexcept
677 : _M_node(__x) { }
678
679 _List_const_iterator(const iterator& __x) _GLIBCXX_NOEXCEPTnoexcept
680 : _M_node(__x._M_node) { }
681
682 iterator
683 _M_const_cast() const _GLIBCXX_NOEXCEPTnoexcept
684 { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); }
685
686 // Must downcast from List_node_base to _List_node to get to value.
687 _GLIBCXX_NODISCARD[[__nodiscard__]]
688 reference
689 operator*() const _GLIBCXX_NOEXCEPTnoexcept
690 { return *static_cast<_Node*>(_M_node)->_M_valptr(); }
691
692 _GLIBCXX_NODISCARD[[__nodiscard__]]
693 pointer
694 operator->() const _GLIBCXX_NOEXCEPTnoexcept
695 { return static_cast<_Node*>(_M_node)->_M_valptr(); }
696
697 _List_const_iterator&
698 operator++() _GLIBCXX_NOEXCEPTnoexcept
699 {
700 _M_node = _M_node->_M_next;
701 return *this;
702 }
703
704 _List_const_iterator
705 operator++(int) _GLIBCXX_NOEXCEPTnoexcept
706 {
707 _List_const_iterator __tmp = *this;
708 _M_node = _M_node->_M_next;
709 return __tmp;
710 }
711
712 _List_const_iterator&
713 operator--() _GLIBCXX_NOEXCEPTnoexcept
714 {
715 _M_node = _M_node->_M_prev;
716 return *this;
717 }
718
719 _List_const_iterator
720 operator--(int) _GLIBCXX_NOEXCEPTnoexcept
721 {
722 _List_const_iterator __tmp = *this;
723 _M_node = _M_node->_M_prev;
724 return __tmp;
725 }
726
727 _GLIBCXX_NODISCARD[[__nodiscard__]]
728 friend bool
729 operator==(const _List_const_iterator& __x,
730 const _List_const_iterator& __y) _GLIBCXX_NOEXCEPTnoexcept
731 { return __x._M_node == __y._M_node; }
732
733#if __cpp_impl_three_way_comparison < 201907L
734 _GLIBCXX_NODISCARD[[__nodiscard__]]
735 friend bool
736 operator!=(const _List_const_iterator& __x,
737 const _List_const_iterator& __y) _GLIBCXX_NOEXCEPTnoexcept
738 { return __x._M_node != __y._M_node; }
739#endif
740
741 // The only member points to the %list element.
742 const __detail::_List_node_base* _M_node;
743 };
744
745_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
746 /// See bits/stl_deque.h's _Deque_base for an explanation.
747 template<typename _Tp, typename _Alloc>
748 class _List_base
749 {
750 protected:
751 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
752 rebind<_Tp>::other _Tp_alloc_type;
753 typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tp_alloc_traits;
754
755 typedef __list::_Node_traits<_Tp, typename _Tp_alloc_traits::pointer>
756 _Node_traits;
757 typedef typename _Tp_alloc_traits::template
758 rebind<typename _Node_traits::_Node>::other _Node_alloc_type;
759 typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
760
761#if __cplusplus201703L < 201103L || ! _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
762 typedef _List_node<_Tp>* _Node_ptr;
763#else
764 using _Node_ptr = typename _Node_alloc_traits::pointer;
765#endif
766
767 struct _List_impl
768 : public _Node_alloc_type
769 {
770 typename _Node_traits::_Node_header _M_node;
771
772 _List_impl() _GLIBCXX_NOEXCEPT_IF(noexcept(is_nothrow_default_constructible<_Node_alloc_type
>::value)
773 is_nothrow_default_constructible<_Node_alloc_type>::value)noexcept(is_nothrow_default_constructible<_Node_alloc_type
>::value)
774 : _Node_alloc_type()
775 { }
776
777 _List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPTnoexcept
778 : _Node_alloc_type(__a)
779 { }
780
781#if __cplusplus201703L >= 201103L
782 _List_impl(_List_impl&&) = default;
783
784 _List_impl(_Node_alloc_type&& __a, _List_impl&& __x)
785 : _Node_alloc_type(std::move(__a)), _M_node(std::move(__x._M_node))
786 { }
787
788 _List_impl(_Node_alloc_type&& __a) noexcept
789 : _Node_alloc_type(std::move(__a))
790 { }
791#endif
792 };
793
794 _List_impl _M_impl;
795
796#if _GLIBCXX_USE_CXX11_ABI1
797 size_t _M_get_size() const { return _M_impl._M_node._M_size; }
798
799 void _M_set_size(size_t __n) { _M_impl._M_node._M_size = __n; }
800
801 void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; }
802
803 void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; }
804#else
805 // dummy implementations used when the size is not stored
806 size_t _M_get_size() const { return 0; }
807 void _M_set_size(size_t) { }
808 void _M_inc_size(size_t) { }
809 void _M_dec_size(size_t) { }
810#endif
811
812 typename _Node_alloc_traits::pointer
813 _M_get_node()
814 { return _Node_alloc_traits::allocate(_M_impl, 1); }
815
816 void
817 _M_put_node(_Node_ptr __p) _GLIBCXX_NOEXCEPTnoexcept
818 {
819#if __cplusplus201703L < 201103L || _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
820 _Node_alloc_traits::deallocate(_M_impl, __p, 1);
821#else
822#pragma GCC diagnostic push
823#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
824 using __alloc_pointer = typename _Node_alloc_traits::pointer;
825 if constexpr (is_same<_Node_ptr, __alloc_pointer>::value)
826 _Node_alloc_traits::deallocate(_M_impl, __p, 1);
827 else
828 {
829 // When not using the allocator's pointer type internally we must
830 // convert __p to __alloc_pointer so it can be deallocated.
831 auto __ap = pointer_traits<__alloc_pointer>::pointer_to(*__p);
832 _Node_alloc_traits::deallocate(_M_impl, __ap, 1);
833 }
834#pragma GCC diagnostic pop
835#endif
836 }
837
838 void
839 _M_destroy_node(_Node_ptr __p)
840 {
841 // Destroy the element
842#if __cplusplus201703L < 201103L
843 _Tp_alloc_type(_M_impl).destroy(__p->_M_valptr());
844#else
845 _Node_alloc_traits::destroy(_M_impl, __p->_M_valptr());
846 // Only destroy the node if the pointers require it.
847 using _Node = typename _Node_traits::_Node;
848 using _Base_ptr = typename _Node_traits::_Node_base::_Base_ptr;
849#pragma GCC diagnostic push
850#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
851 if constexpr (!is_trivially_destructible<_Base_ptr>::value)
852 __p->~_Node();
853#pragma GCC diagnostic pop
854#endif
855 this->_M_put_node(__p);
856 }
857
858 public:
859 typedef _Alloc allocator_type;
860
861 _Node_alloc_type&
862 _M_get_Node_allocator() _GLIBCXX_NOEXCEPTnoexcept
863 { return _M_impl; }
864
865 const _Node_alloc_type&
866 _M_get_Node_allocator() const _GLIBCXX_NOEXCEPTnoexcept
867 { return _M_impl; }
868
869#if __cplusplus201703L >= 201103L
870 _List_base() = default;
871#else
872 _List_base() { }
873#endif
874
875 _List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPTnoexcept
876 : _M_impl(__a)
877 { }
878
879#if __cplusplus201703L >= 201103L
880 _List_base(_List_base&&) = default;
881
882 // Used when allocator is_always_equal.
883 _List_base(_Node_alloc_type&& __a, _List_base&& __x)
884 : _M_impl(std::move(__a), std::move(__x._M_impl))
885 { }
886
887 // Used when allocator !is_always_equal.
888 _List_base(_Node_alloc_type&& __a)
889 : _M_impl(std::move(__a))
890 { }
891
892 void
893 _M_move_nodes(_List_base&& __x)
894 { _M_impl._M_node._M_move_nodes(std::move(__x._M_impl._M_node)); }
895#endif
896
897 // This is what actually destroys the list.
898 ~_List_base() _GLIBCXX_NOEXCEPTnoexcept
899 { _M_clear(); }
900
901 void
902 _M_clear() _GLIBCXX_NOEXCEPTnoexcept;
903
904 void
905 _M_init() _GLIBCXX_NOEXCEPTnoexcept
906 { this->_M_impl._M_node._M_init(); }
907
908#if !_GLIBCXX_INLINE_VERSION0
909 // XXX GLIBCXX_ABI Deprecated
910 // These members are unused by std::list now, but we keep them here
911 // so that an explicit instantiation of std::list will define them.
912 // This ensures that explicit instantiations still define these symbols,
913 // so that explicit instantiation declarations of std::list that were
914 // compiled with old versions of GCC can still find these old symbols.
915
916 // Use 'if constexpr' so that the functions don't do anything for
917 // specializations using _Node_traits<T, fancy-pointer>, because any
918 // old code referencing these symbols wasn't using the fancy-pointer
919 // specializations.
920
921#pragma GCC diagnostic push
922#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
923
924# if __cplusplus201703L >= 201103L
925 _List_base(_List_base&& __x, _Node_alloc_type&& __a)
926 : _M_impl(std::move(__a))
927 {
928#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
929 if constexpr (is_same<typename _Tp_alloc_traits::pointer, _Tp*>::value)
930#endif
931 if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
932 _M_move_nodes(std::move(__x));
933 // else caller must move individual elements.
934 }
935# endif
936
937 static size_t
938 _S_distance(const __detail::_List_node_base* __first,
939 const __detail::_List_node_base* __last)
940 {
941#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
942 if constexpr (!is_same<typename _Tp_alloc_traits::pointer, _Tp*>::value)
943 return 0;
944 else
945#endif
946 {
947 size_t __n = 0;
948 while (__first != __last)
949 {
950 __first = __first->_M_next;
951 ++__n;
952 }
953 return __n;
954 }
955 }
956
957#if _GLIBCXX_USE_CXX11_ABI1
958 size_t
959 _M_distance(const __detail::_List_node_base* __first,
960 const __detail::_List_node_base* __last) const
961 { return _S_distance(__first, __last); }
962
963 // return the stored size
964 size_t _M_node_count() const { return _M_get_size(); }
965#else
966 size_t _M_distance(const void*, const void*) const { return 0; }
967
968 // count the number of nodes
969 size_t _M_node_count() const
970 {
971 return _S_distance(_M_impl._M_node._M_next, _M_impl._M_node._M_base());
972 }
973#endif
974#pragma GCC diagnostic pop
975#endif // ! INLINE_VERSION
976 };
977
978 /**
979 * @brief A standard container with linear time access to elements,
980 * and fixed time insertion/deletion at any point in the sequence.
981 *
982 * @ingroup sequences
983 *
984 * @tparam _Tp Type of element.
985 * @tparam _Alloc Allocator type, defaults to allocator<_Tp>.
986 *
987 * Meets the requirements of a <a href="tables.html#65">container</a>, a
988 * <a href="tables.html#66">reversible container</a>, and a
989 * <a href="tables.html#67">sequence</a>, including the
990 * <a href="tables.html#68">optional sequence requirements</a> with the
991 * %exception of @c at and @c operator[].
992 *
993 * This is a @e doubly @e linked %list. Traversal up and down the
994 * %list requires linear time, but adding and removing elements (or
995 * @e nodes) is done in constant time, regardless of where the
996 * change takes place. Unlike std::vector and std::deque,
997 * random-access iterators are not provided, so subscripting ( @c
998 * [] ) access is not allowed. For algorithms which only need
999 * sequential access, this lack makes no difference.
1000 *
1001 * Also unlike the other standard containers, std::list provides
1002 * specialized algorithms %unique to linked lists, such as
1003 * splicing, sorting, and in-place reversal.
1004 *
1005 * A couple points on memory allocation for list<Tp>:
1006 *
1007 * First, we never actually allocate a Tp, we allocate
1008 * List_node<Tp>'s and trust [20.1.5]/4 to DTRT. This is to ensure
1009 * that after elements from %list<X,Alloc1> are spliced into
1010 * %list<X,Alloc2>, destroying the memory of the second %list is a
1011 * valid operation, i.e., Alloc1 giveth and Alloc2 taketh away.
1012 *
1013 * Second, a %list conceptually represented as
1014 * @code
1015 * A <---> B <---> C <---> D
1016 * @endcode
1017 * is actually circular; a link exists between A and D. The %list
1018 * class holds (as its only data member) a private list::iterator
1019 * pointing to @e D, not to @e A! To get to the head of the %list,
1020 * we start at the tail and move forward by one. When this member
1021 * iterator's next/previous pointers refer to itself, the %list is
1022 * %empty.
1023 */
1024 template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
1025 class list : protected _List_base<_Tp, _Alloc>
1026 {
1027#ifdef _GLIBCXX_CONCEPT_CHECKS
1028 // concept requirements
1029 typedef typename _Alloc::value_type _Alloc_value_type;
1030# if __cplusplus201703L < 201103L
1031 __glibcxx_class_requires(_Tp, _SGIAssignableConcept)
1032# endif
1033 __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept)
1034#endif
1035
1036#if __cplusplus201703L >= 201103L
1037 static_assert(is_same<typename remove_cv<_Tp>::type, _Tp>::value,
1038 "std::list must have a non-const, non-volatile value_type");
1039# if __cplusplus201703L > 201703L || defined __STRICT_ANSI__
1040 static_assert(is_same<typename _Alloc::value_type, _Tp>::value,
1041 "std::list must have the same value_type as its allocator");
1042# endif
1043#endif
1044
1045 typedef _List_base<_Tp, _Alloc> _Base;
1046 typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
1047 typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits;
1048 typedef typename _Base::_Node_alloc_type _Node_alloc_type;
1049 typedef typename _Base::_Node_alloc_traits _Node_alloc_traits;
1050 typedef typename _Base::_Node_traits _Node_traits;
1051
1052 public:
1053 typedef _Tp value_type;
1054 typedef typename _Tp_alloc_traits::pointer pointer;
1055 typedef typename _Tp_alloc_traits::const_pointer const_pointer;
1056 typedef typename _Tp_alloc_traits::reference reference;
1057 typedef typename _Tp_alloc_traits::const_reference const_reference;
1058 typedef typename _Node_traits::_Iterator iterator;
1059 typedef typename _Node_traits::_Const_iterator const_iterator;
1060 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1061 typedef std::reverse_iterator<iterator> reverse_iterator;
1062 typedef size_t size_type;
1063 typedef ptrdiff_t difference_type;
1064 typedef _Alloc allocator_type;
1065
1066 protected:
1067 // Note that pointers-to-_Node's can be ctor-converted to
1068 // iterator types.
1069 typedef typename _Node_alloc_traits::pointer _Node_ptr;
1070
1071 using _Base::_M_impl;
1072 using _Base::_M_put_node;
1073 using _Base::_M_get_node;
1074 using _Base::_M_get_Node_allocator;
1075
1076 /**
1077 * @param __args An instance of user data.
1078 *
1079 * Allocates space for a new node and constructs a copy of
1080 * @a __args in it.
1081 */
1082#if __cplusplus201703L < 201103L
1083 _Node_ptr
1084 _M_create_node(const value_type& __x)
1085 {
1086 _Node_ptr __p = this->_M_get_node();
1087 __trytry
1088 {
1089 _Tp_alloc_type __alloc(_M_get_Node_allocator());
1090 __alloc.construct(__p->_M_valptr(), __x);
1091 }
1092 __catch(...)catch(...)
1093 {
1094 _M_put_node(__p);
1095 __throw_exception_againthrow;
1096 }
1097 return __p;
1098 }
1099#else
1100 template<typename... _Args>
1101 _Node_ptr
1102 _M_create_node(_Args&&... __args)
1103 {
1104 auto& __alloc = _M_get_Node_allocator();
1105 auto __guard = std::__allocate_guarded_obj(__alloc);
1106 _Node_alloc_traits::construct(__alloc, __guard->_M_valptr(),
1107 std::forward<_Args>(__args)...);
1108 return __guard.release();
1109 }
1110#endif
1111
1112 public:
1113 // [23.2.2.1] construct/copy/destroy
1114 // (assign() and get_allocator() are also listed in this section)
1115
1116 /**
1117 * @brief Creates a %list with no elements.
1118 */
1119#if __cplusplus201703L >= 201103L
1120 list() = default;
1121#else
1122 list() { }
1123#endif
1124
1125 /**
1126 * @brief Creates a %list with no elements.
1127 * @param __a An allocator object.
1128 */
1129 explicit
1130 list(const allocator_type& __a) _GLIBCXX_NOEXCEPTnoexcept
1131 : _Base(_Node_alloc_type(__a)) { }
1132
1133#if __cplusplus201703L >= 201103L
1134 /**
1135 * @brief Creates a %list with default constructed elements.
1136 * @param __n The number of elements to initially create.
1137 * @param __a An allocator object.
1138 *
1139 * This constructor fills the %list with @a __n default
1140 * constructed elements.
1141 */
1142 explicit
1143 list(size_type __n, const allocator_type& __a = allocator_type())
1144 : _Base(_Node_alloc_type(__a))
1145 { _M_default_initialize(__n); }
1146
1147 /**
1148 * @brief Creates a %list with copies of an exemplar element.
1149 * @param __n The number of elements to initially create.
1150 * @param __value An element to copy.
1151 * @param __a An allocator object.
1152 *
1153 * This constructor fills the %list with @a __n copies of @a __value.
1154 */
1155 list(size_type __n, const value_type& __value,
1156 const allocator_type& __a = allocator_type())
1157 : _Base(_Node_alloc_type(__a))
1158 { _M_fill_initialize(__n, __value); }
1159#else
1160 /**
1161 * @brief Creates a %list with copies of an exemplar element.
1162 * @param __n The number of elements to initially create.
1163 * @param __value An element to copy.
1164 * @param __a An allocator object.
1165 *
1166 * This constructor fills the %list with @a __n copies of @a __value.
1167 */
1168 explicit
1169 list(size_type __n, const value_type& __value = value_type(),
1170 const allocator_type& __a = allocator_type())
1171 : _Base(_Node_alloc_type(__a))
1172 { _M_fill_initialize(__n, __value); }
1173#endif
1174
1175 /**
1176 * @brief %List copy constructor.
1177 * @param __x A %list of identical element and allocator types.
1178 *
1179 * The newly-created %list uses a copy of the allocation object used
1180 * by @a __x (unless the allocator traits dictate a different object).
1181 */
1182 list(const list& __x)
1183 : _Base(_Node_alloc_traits::
1184 _S_select_on_copy(__x._M_get_Node_allocator()))
1185 { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
1186
1187#if __cplusplus201703L >= 201103L
1188 /**
1189 * @brief %List move constructor.
1190 *
1191 * The newly-created %list contains the exact contents of the moved
1192 * instance. The contents of the moved instance are a valid, but
1193 * unspecified %list.
1194 */
1195 list(list&&) = default;
1196
1197 /**
1198 * @brief Builds a %list from an initializer_list
1199 * @param __l An initializer_list of value_type.
1200 * @param __a An allocator object.
1201 *
1202 * Create a %list consisting of copies of the elements in the
1203 * initializer_list @a __l. This is linear in __l.size().
1204 */
1205 list(initializer_list<value_type> __l,
1206 const allocator_type& __a = allocator_type())
1207 : _Base(_Node_alloc_type(__a))
1208 { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); }
1209
1210 list(const list& __x, const __type_identity_t<allocator_type>& __a)
1211 : _Base(_Node_alloc_type(__a))
1212 { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
1213
1214 private:
1215 list(list&& __x, const allocator_type& __a, true_type) noexcept
1216 : _Base(_Node_alloc_type(__a), std::move(__x))
1217 { }
1218
1219 list(list&& __x, const allocator_type& __a, false_type)
1220 : _Base(_Node_alloc_type(__a))
1221 {
1222 if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator())
1223 this->_M_move_nodes(std::move(__x));
1224 else
1225 insert(begin(), std::__make_move_if_noexcept_iterator(__x.begin()),
1226 std::__make_move_if_noexcept_iterator(__x.end()));
1227 }
1228
1229 public:
1230 list(list&& __x, const __type_identity_t<allocator_type>& __a)
1231 noexcept(_Node_alloc_traits::_S_always_equal())
1232 : list(std::move(__x), __a,
1233 typename _Node_alloc_traits::is_always_equal{})
1234 { }
1235#endif
1236
1237 /**
1238 * @brief Builds a %list from a range.
1239 * @param __first An input iterator.
1240 * @param __last An input iterator.
1241 * @param __a An allocator object.
1242 *
1243 * Create a %list consisting of copies of the elements from
1244 * [@a __first,@a __last). This is linear in N (where N is
1245 * distance(@a __first,@a __last)).
1246 */
1247#if __cplusplus201703L >= 201103L
1248 template<typename _InputIterator,
1249 typename = std::_RequireInputIter<_InputIterator>>
1250 list(_InputIterator __first, _InputIterator __last,
1251 const allocator_type& __a = allocator_type())
1252 : _Base(_Node_alloc_type(__a))
1253 { _M_initialize_dispatch(__first, __last, __false_type()); }
1254#else
1255 template<typename _InputIterator>
1256 list(_InputIterator __first, _InputIterator __last,
1257 const allocator_type& __a = allocator_type())
1258 : _Base(_Node_alloc_type(__a))
1259 {
1260 // Check whether it's an integral type. If so, it's not an iterator.
1261 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
1262 _M_initialize_dispatch(__first, __last, _Integral());
1263 }
1264#endif
1265
1266#if __glibcxx_containers_ranges // C++ >= 23
1267 /**
1268 * @brief Construct a list from a range.
1269 * @since C++23
1270 */
1271 template<__detail::__container_compatible_range<_Tp> _Rg>
1272 list(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
1273 : _Base(_Node_alloc_type(__a))
1274 {
1275 auto __first = ranges::begin(__rg);
1276 const auto __last = ranges::end(__rg);
1277 for (; __first != __last; ++__first)
1278 emplace_back(*__first);
1279 }
1280#endif
1281
1282#if __cplusplus201703L >= 201103L
1283 /**
1284 * No explicit dtor needed as the _Base dtor takes care of
1285 * things. The _Base dtor only erases the elements, and note
1286 * that if the elements themselves are pointers, the pointed-to
1287 * memory is not touched in any way. Managing the pointer is
1288 * the user's responsibility.
1289 */
1290 ~list() = default;
1291#endif
1292
1293 /**
1294 * @brief %List assignment operator.
1295 * @param __x A %list of identical element and allocator types.
1296 *
1297 * All the elements of @a __x are copied.
1298 *
1299 * Whether the allocator is copied depends on the allocator traits.
1300 */
1301 list&
1302 operator=(const list& __x);
1303
1304#if __cplusplus201703L >= 201103L
1305#pragma GCC diagnostic push
1306#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
1307 /**
1308 * @brief %List move assignment operator.
1309 * @param __x A %list of identical element and allocator types.
1310 *
1311 * The contents of @a __x are moved into this %list (without copying).
1312 *
1313 * Afterwards @a __x is a valid, but unspecified %list
1314 *
1315 * Whether the allocator is moved depends on the allocator traits.
1316 */
1317 list&
1318 operator=(list&& __x)
1319 noexcept(_Node_alloc_traits::_S_nothrow_move())
1320 {
1321 constexpr bool __move_storage =
1322 _Node_alloc_traits::_S_propagate_on_move_assign()
1323 || _Node_alloc_traits::_S_always_equal();
1324 if constexpr (!__move_storage)
1325 {
1326 if (__x._M_get_Node_allocator() != this->_M_get_Node_allocator())
1327 {
1328 // The rvalue's allocator cannot be moved, or is not equal,
1329 // so we need to individually move each element.
1330 _M_assign_dispatch(std::make_move_iterator(__x.begin()),
1331 std::make_move_iterator(__x.end()),
1332 __false_type{});
1333 return *this;
1334 }
1335 }
1336
1337 this->clear();
1338 this->_M_move_nodes(std::move(__x));
1339
1340 if constexpr (_Node_alloc_traits::_S_propagate_on_move_assign())
1341 this->_M_get_Node_allocator()
1342 = std::move(__x._M_get_Node_allocator());
1343
1344 return *this;
1345 }
1346#pragma GCC diagnostic pop
1347
1348 /**
1349 * @brief %List initializer list assignment operator.
1350 * @param __l An initializer_list of value_type.
1351 *
1352 * Replace the contents of the %list with copies of the elements
1353 * in the initializer_list @a __l. This is linear in l.size().
1354 */
1355 list&
1356 operator=(initializer_list<value_type> __l)
1357 {
1358 this->assign(__l.begin(), __l.end());
1359 return *this;
1360 }
1361#endif
1362
1363#if __glibcxx_containers_ranges // C++ >= 23
1364 /**
1365 * @brief Assign a range to a list.
1366 * @since C++23
1367 */
1368 template<__detail::__container_compatible_range<_Tp> _Rg>
1369 void
1370 assign_range(_Rg&& __rg)
1371 {
1372 static_assert(assignable_from<_Tp&, ranges::range_reference_t<_Rg>>);
1373
1374 iterator __first1 = begin();
1375 const iterator __last1 = end();
1376 auto __first2 = ranges::begin(__rg);
1377 const auto __last2 = ranges::end(__rg);
1378 for (; __first1 != __last1 && __first2 != __last2;
1379 ++__first1, (void)++__first2)
1380 *__first1 = *__first2;
1381 if (__first2 == __last2)
1382 erase(__first1, __last1);
1383 else
1384 insert_range(__last1,
1385 ranges::subrange(std::move(__first2), __last2));
1386 }
1387#endif
1388
1389 /**
1390 * @brief Assigns a given value to a %list.
1391 * @param __n Number of elements to be assigned.
1392 * @param __val Value to be assigned.
1393 *
1394 * This function fills a %list with @a __n copies of the given
1395 * value. Note that the assignment completely changes the %list
1396 * and that the resulting %list's size is the same as the number
1397 * of elements assigned.
1398 */
1399 void
1400 assign(size_type __n, const value_type& __val)
1401 { _M_fill_assign(__n, __val); }
1402
1403 /**
1404 * @brief Assigns a range to a %list.
1405 * @param __first An input iterator.
1406 * @param __last An input iterator.
1407 *
1408 * This function fills a %list with copies of the elements in the
1409 * range [@a __first,@a __last).
1410 *
1411 * Note that the assignment completely changes the %list and
1412 * that the resulting %list's size is the same as the number of
1413 * elements assigned.
1414 */
1415#if __cplusplus201703L >= 201103L
1416 template<typename _InputIterator,
1417 typename = std::_RequireInputIter<_InputIterator>>
1418 void
1419 assign(_InputIterator __first, _InputIterator __last)
1420 { _M_assign_dispatch(__first, __last, __false_type()); }
1421#else
1422 template<typename _InputIterator>
1423 void
1424 assign(_InputIterator __first, _InputIterator __last)
1425 {
1426 // Check whether it's an integral type. If so, it's not an iterator.
1427 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
1428 _M_assign_dispatch(__first, __last, _Integral());
1429 }
1430#endif
1431
1432#if __cplusplus201703L >= 201103L
1433 /**
1434 * @brief Assigns an initializer_list to a %list.
1435 * @param __l An initializer_list of value_type.
1436 *
1437 * Replace the contents of the %list with copies of the elements
1438 * in the initializer_list @a __l. This is linear in __l.size().
1439 */
1440 void
1441 assign(initializer_list<value_type> __l)
1442 { this->_M_assign_dispatch(__l.begin(), __l.end(), __false_type()); }
1443#endif
1444
1445 /// Get a copy of the memory allocation object.
1446 allocator_type
1447 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
1448 { return allocator_type(_Base::_M_get_Node_allocator()); }
1449
1450 // iterators
1451 /**
1452 * Returns a read/write iterator that points to the first element in the
1453 * %list. Iteration is done in ordinary element order.
1454 */
1455 _GLIBCXX_NODISCARD[[__nodiscard__]]
1456 iterator
1457 begin() _GLIBCXX_NOEXCEPTnoexcept
1458 { return iterator(this->_M_impl._M_node._M_next); }
1459
1460 /**
1461 * Returns a read-only (constant) iterator that points to the
1462 * first element in the %list. Iteration is done in ordinary
1463 * element order.
1464 */
1465 _GLIBCXX_NODISCARD[[__nodiscard__]]
1466 const_iterator
1467 begin() const _GLIBCXX_NOEXCEPTnoexcept
1468 { return const_iterator(this->_M_impl._M_node._M_next); }
1469
1470 /**
1471 * Returns a read/write iterator that points one past the last
1472 * element in the %list. Iteration is done in ordinary element
1473 * order.
1474 */
1475 _GLIBCXX_NODISCARD[[__nodiscard__]]
1476 iterator
1477 end() _GLIBCXX_NOEXCEPTnoexcept
1478 { return iterator(this->_M_impl._M_node._M_base()); }
1479
1480 /**
1481 * Returns a read-only (constant) iterator that points one past
1482 * the last element in the %list. Iteration is done in ordinary
1483 * element order.
1484 */
1485 _GLIBCXX_NODISCARD[[__nodiscard__]]
1486 const_iterator
1487 end() const _GLIBCXX_NOEXCEPTnoexcept
1488 { return const_iterator(this->_M_impl._M_node._M_base()); }
1489
1490 /**
1491 * Returns a read/write reverse iterator that points to the last
1492 * element in the %list. Iteration is done in reverse element
1493 * order.
1494 */
1495 _GLIBCXX_NODISCARD[[__nodiscard__]]
1496 reverse_iterator
1497 rbegin() _GLIBCXX_NOEXCEPTnoexcept
1498 { return reverse_iterator(end()); }
1499
1500 /**
1501 * Returns a read-only (constant) reverse iterator that points to
1502 * the last element in the %list. Iteration is done in reverse
1503 * element order.
1504 */
1505 _GLIBCXX_NODISCARD[[__nodiscard__]]
1506 const_reverse_iterator
1507 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
1508 { return const_reverse_iterator(end()); }
1509
1510 /**
1511 * Returns a read/write reverse iterator that points to one
1512 * before the first element in the %list. Iteration is done in
1513 * reverse element order.
1514 */
1515 _GLIBCXX_NODISCARD[[__nodiscard__]]
1516 reverse_iterator
1517 rend() _GLIBCXX_NOEXCEPTnoexcept
1518 { return reverse_iterator(begin()); }
1519
1520 /**
1521 * Returns a read-only (constant) reverse iterator that points to one
1522 * before the first element in the %list. Iteration is done in reverse
1523 * element order.
1524 */
1525 _GLIBCXX_NODISCARD[[__nodiscard__]]
1526 const_reverse_iterator
1527 rend() const _GLIBCXX_NOEXCEPTnoexcept
1528 { return const_reverse_iterator(begin()); }
1529
1530#if __cplusplus201703L >= 201103L
1531 /**
1532 * Returns a read-only (constant) iterator that points to the
1533 * first element in the %list. Iteration is done in ordinary
1534 * element order.
1535 */
1536 [[__nodiscard__]]
1537 const_iterator
1538 cbegin() const noexcept
1539 { return const_iterator(this->_M_impl._M_node._M_next); }
1540
1541 /**
1542 * Returns a read-only (constant) iterator that points one past
1543 * the last element in the %list. Iteration is done in ordinary
1544 * element order.
1545 */
1546 [[__nodiscard__]]
1547 const_iterator
1548 cend() const noexcept
1549 { return const_iterator(this->_M_impl._M_node._M_base()); }
1550
1551 /**
1552 * Returns a read-only (constant) reverse iterator that points to
1553 * the last element in the %list. Iteration is done in reverse
1554 * element order.
1555 */
1556 [[__nodiscard__]]
1557 const_reverse_iterator
1558 crbegin() const noexcept
1559 { return const_reverse_iterator(end()); }
1560
1561 /**
1562 * Returns a read-only (constant) reverse iterator that points to one
1563 * before the first element in the %list. Iteration is done in reverse
1564 * element order.
1565 */
1566 [[__nodiscard__]]
1567 const_reverse_iterator
1568 crend() const noexcept
1569 { return const_reverse_iterator(begin()); }
1570#endif
1571
1572 // [23.2.2.2] capacity
1573 /**
1574 * Returns true if the %list is empty. (Thus begin() would equal
1575 * end().)
1576 */
1577 _GLIBCXX_NODISCARD[[__nodiscard__]] bool
1578 empty() const _GLIBCXX_NOEXCEPTnoexcept
1579 {
1580 return this->_M_impl._M_node._M_next == this->_M_impl._M_node._M_base();
1581 }
1582
1583 /** Returns the number of elements in the %list. */
1584 _GLIBCXX_NODISCARD[[__nodiscard__]]
1585 size_type
1586 size() const _GLIBCXX_NOEXCEPTnoexcept
1587 {
1588#if _GLIBCXX_USE_CXX11_ABI1
1589 return this->_M_get_size(); // return the stored size
1590#else
1591 return std::distance(begin(), end()); // count the number of nodes
1592#endif
1593 }
1594
1595 /** Returns the size() of the largest possible %list. */
1596 _GLIBCXX_NODISCARD[[__nodiscard__]]
1597 size_type
1598 max_size() const _GLIBCXX_NOEXCEPTnoexcept
1599 { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); }
1600
1601#if __cplusplus201703L >= 201103L
1602 /**
1603 * @brief Resizes the %list to the specified number of elements.
1604 * @param __new_size Number of elements the %list should contain.
1605 *
1606 * This function will %resize the %list to the specified number
1607 * of elements. If the number is smaller than the %list's
1608 * current size the %list is truncated, otherwise default
1609 * constructed elements are appended.
1610 */
1611 void
1612 resize(size_type __new_size);
1613
1614 /**
1615 * @brief Resizes the %list to the specified number of elements.
1616 * @param __new_size Number of elements the %list should contain.
1617 * @param __x Data with which new elements should be populated.
1618 *
1619 * This function will %resize the %list to the specified number
1620 * of elements. If the number is smaller than the %list's
1621 * current size the %list is truncated, otherwise the %list is
1622 * extended and new elements are populated with given data.
1623 */
1624 void
1625 resize(size_type __new_size, const value_type& __x);
1626#else
1627 /**
1628 * @brief Resizes the %list to the specified number of elements.
1629 * @param __new_size Number of elements the %list should contain.
1630 * @param __x Data with which new elements should be populated.
1631 *
1632 * This function will %resize the %list to the specified number
1633 * of elements. If the number is smaller than the %list's
1634 * current size the %list is truncated, otherwise the %list is
1635 * extended and new elements are populated with given data.
1636 */
1637 void
1638 resize(size_type __new_size, value_type __x = value_type());
1639#endif
1640
1641 // element access
1642 /**
1643 * Returns a read/write reference to the data at the first
1644 * element of the %list.
1645 */
1646 _GLIBCXX_NODISCARD[[__nodiscard__]]
1647 reference
1648 front() _GLIBCXX_NOEXCEPTnoexcept
1649 {
1650 __glibcxx_requires_nonempty()do { if (std::__is_constant_evaluated() && !bool(!this
->empty())) std::__glibcxx_assert_fail(); } while (false)
;
1651 return *begin();
1652 }
1653
1654 /**
1655 * Returns a read-only (constant) reference to the data at the first
1656 * element of the %list.
1657 */
1658 _GLIBCXX_NODISCARD[[__nodiscard__]]
1659 const_reference
1660 front() const _GLIBCXX_NOEXCEPTnoexcept
1661 {
1662 __glibcxx_requires_nonempty()do { if (std::__is_constant_evaluated() && !bool(!this
->empty())) std::__glibcxx_assert_fail(); } while (false)
;
1663 return *begin();
1664 }
1665
1666 /**
1667 * Returns a read/write reference to the data at the last element
1668 * of the %list.
1669 */
1670 _GLIBCXX_NODISCARD[[__nodiscard__]]
1671 reference
1672 back() _GLIBCXX_NOEXCEPTnoexcept
1673 {
1674 __glibcxx_requires_nonempty()do { if (std::__is_constant_evaluated() && !bool(!this
->empty())) std::__glibcxx_assert_fail(); } while (false)
;
1675 iterator __tmp = end();
1676 --__tmp;
1677 return *__tmp;
1678 }
1679
1680 /**
1681 * Returns a read-only (constant) reference to the data at the last
1682 * element of the %list.
1683 */
1684 _GLIBCXX_NODISCARD[[__nodiscard__]]
1685 const_reference
1686 back() const _GLIBCXX_NOEXCEPTnoexcept
1687 {
1688 __glibcxx_requires_nonempty()do { if (std::__is_constant_evaluated() && !bool(!this
->empty())) std::__glibcxx_assert_fail(); } while (false)
;
1689 const_iterator __tmp = end();
1690 --__tmp;
1691 return *__tmp;
1692 }
1693
1694 // [23.2.2.3] modifiers
1695 /**
1696 * @brief Add data to the front of the %list.
1697 * @param __x Data to be added.
1698 *
1699 * This is a typical stack operation. The function creates an
1700 * element at the front of the %list and assigns the given data
1701 * to it. Due to the nature of a %list this operation can be
1702 * done in constant time, and does not invalidate iterators and
1703 * references.
1704 */
1705 void
1706 push_front(const value_type& __x)
1707 { this->_M_insert(begin(), __x); }
1708
1709#if __cplusplus201703L >= 201103L
1710 void
1711 push_front(value_type&& __x)
1712 { this->_M_insert(begin(), std::move(__x)); }
1713
1714 template<typename... _Args>
1715#if __cplusplus201703L > 201402L
1716 reference
1717#else
1718 void
1719#endif
1720 emplace_front(_Args&&... __args)
1721 {
1722 this->_M_insert(begin(), std::forward<_Args>(__args)...);
1723#if __cplusplus201703L > 201402L
1724 return front();
1725#endif
1726 }
1727#endif
1728
1729#if __glibcxx_containers_ranges // C++ >= 23
1730 /**
1731 * @brief Insert a range at the beginning of a list.
1732 * @param __rg An input range of elements that can be converted to
1733 * the list's value type.
1734 *
1735 * Inserts the elements of `__rg` at the beginning of the list.
1736 * No iterators to existing elements are invalidated by this function.
1737 * If the insertion fails due to an exception, no elements will be added
1738 * and so the list will be unchanged.
1739 *
1740 * @since C++23
1741 */
1742 template<__detail::__container_compatible_range<_Tp> _Rg>
1743 void
1744 prepend_range(_Rg&& __rg)
1745 {
1746 list __tmp(from_range, std::forward<_Rg>(__rg), get_allocator());
1747 if (!__tmp.empty())
1748 splice(begin(), __tmp);
1749 }
1750
1751 /**
1752 * @brief Insert a range at the end of a list.
1753 * @param __rg An input range of elements that can be converted to
1754 * the list's value type.
1755 *
1756 * Inserts the elements of `__rg` at the end of the list.
1757 * No iterators to existing elements are invalidated by this function.
1758 * If the insertion fails due to an exception, no elements will be added
1759 * and so the list will be unchanged.
1760 *
1761 * @since C++23
1762 */
1763 template<__detail::__container_compatible_range<_Tp> _Rg>
1764 void
1765 append_range(_Rg&& __rg)
1766 {
1767 list __tmp(from_range, std::forward<_Rg>(__rg), get_allocator());
1768 if (!__tmp.empty())
1769 splice(end(), __tmp);
1770 }
1771#endif
1772
1773 /**
1774 * @brief Removes first element.
1775 *
1776 * This is a typical stack operation. It shrinks the %list by
1777 * one. Due to the nature of a %list this operation can be done
1778 * in constant time, and only invalidates iterators/references to
1779 * the element being removed.
1780 *
1781 * Note that no data is returned, and if the first element's data
1782 * is needed, it should be retrieved before pop_front() is
1783 * called.
1784 */
1785 void
1786 pop_front() _GLIBCXX_NOEXCEPTnoexcept
1787 {
1788 __glibcxx_requires_nonempty()do { if (std::__is_constant_evaluated() && !bool(!this
->empty())) std::__glibcxx_assert_fail(); } while (false)
;
1789 this->_M_erase(begin());
1790 }
1791
1792 /**
1793 * @brief Add data to the end of the %list.
1794 * @param __x Data to be added.
1795 *
1796 * This is a typical stack operation. The function creates an
1797 * element at the end of the %list and assigns the given data to
1798 * it. Due to the nature of a %list this operation can be done
1799 * in constant time, and does not invalidate iterators and
1800 * references.
1801 */
1802 void
1803 push_back(const value_type& __x)
1804 { this->_M_insert(end(), __x); }
1805
1806#if __cplusplus201703L >= 201103L
1807 void
1808 push_back(value_type&& __x)
1809 { this->_M_insert(end(), std::move(__x)); }
1810
1811 template<typename... _Args>
1812#if __cplusplus201703L > 201402L
1813 reference
1814#else
1815 void
1816#endif
1817 emplace_back(_Args&&... __args)
1818 {
1819 this->_M_insert(end(), std::forward<_Args>(__args)...);
1820#if __cplusplus201703L > 201402L
1821 return back();
1822#endif
1823 }
1824#endif
1825
1826 /**
1827 * @brief Removes last element.
1828 *
1829 * This is a typical stack operation. It shrinks the %list by
1830 * one. Due to the nature of a %list this operation can be done
1831 * in constant time, and only invalidates iterators/references to
1832 * the element being removed.
1833 *
1834 * Note that no data is returned, and if the last element's data
1835 * is needed, it should be retrieved before pop_back() is called.
1836 */
1837 void
1838 pop_back() _GLIBCXX_NOEXCEPTnoexcept
1839 {
1840 __glibcxx_requires_nonempty()do { if (std::__is_constant_evaluated() && !bool(!this
->empty())) std::__glibcxx_assert_fail(); } while (false)
;
1841 this->_M_erase(iterator(this->_M_impl._M_node._M_prev));
1842 }
1843
1844#if __cplusplus201703L >= 201103L
1845 /**
1846 * @brief Constructs object in %list before specified iterator.
1847 * @param __position A const_iterator into the %list.
1848 * @param __args Arguments.
1849 * @return An iterator that points to the inserted data.
1850 *
1851 * This function will insert an object of type T constructed
1852 * with T(std::forward<Args>(args)...) before the specified
1853 * location. Due to the nature of a %list this operation can
1854 * be done in constant time, and does not invalidate iterators
1855 * and references.
1856 */
1857 template<typename... _Args>
1858 iterator
1859 emplace(const_iterator __position, _Args&&... __args);
1860#endif
1861
1862 /**
1863 * @brief Inserts given value into %list before specified iterator.
1864 * @param __position An iterator into the %list.
1865 * @param __x Data to be inserted.
1866 * @return An iterator that points to the inserted data.
1867 *
1868 * This function will insert a copy of the given value before
1869 * the specified location. Due to the nature of a %list this
1870 * operation can be done in constant time, and does not
1871 * invalidate iterators and references.
1872 *
1873 * @{
1874 */
1875#if __cplusplus201703L >= 201103L
1876 iterator
1877 insert(const_iterator __position, const value_type& __x);
1878
1879 iterator
1880 insert(const_iterator __position, value_type&& __x)
1881 { return emplace(__position, std::move(__x)); }
1882#else
1883 iterator
1884 insert(iterator __position, const value_type& __x);
1885#endif
1886 /// @}
1887
1888#if __cplusplus201703L >= 201103L
1889 /**
1890 * @brief Inserts the contents of an initializer_list into %list
1891 * before specified const_iterator.
1892 * @param __p A const_iterator into the %list.
1893 * @param __l An initializer_list of value_type.
1894 * @return An iterator pointing to the first element inserted
1895 * (or `__p`).
1896 *
1897 * This function will insert copies of the data in the
1898 * initializer_list `__l` into the %list before the location
1899 * specified by `__p`.
1900 *
1901 * This operation is linear in the number of elements inserted and
1902 * does not invalidate iterators and references.
1903 */
1904 iterator
1905 insert(const_iterator __p, initializer_list<value_type> __l)
1906 { return this->insert(__p, __l.begin(), __l.end()); }
1907#endif
1908
1909 /**
1910 * @brief Inserts a number of copies of given data into the %list.
1911 * @param __position An iterator into the %list.
1912 * @param __n Number of elements to be inserted.
1913 * @param __x Data to be inserted.
1914 * @return Since C++11, an iterator pointing to the first element
1915 * inserted (or `__position`). In C++98 this returns void.
1916 *
1917 * This function will insert a specified number of copies of the
1918 * given data before the location specified by `__position`.
1919 *
1920 * This operation is linear in the number of elements inserted and
1921 * does not invalidate iterators and references.
1922 */
1923#if __cplusplus201703L >= 201103L
1924 iterator
1925 insert(const_iterator __position, size_type __n, const value_type& __x);
1926#else
1927 void
1928 insert(iterator __position, size_type __n, const value_type& __x)
1929 {
1930 list __tmp(__n, __x, get_allocator());
1931 splice(__position, __tmp);
1932 }
1933#endif
1934
1935 /**
1936 * @brief Inserts a range into the %list.
1937 * @param __position An iterator into the %list.
1938 * @param __first An input iterator.
1939 * @param __last An input iterator.
1940 * @return Since C++11, an iterator pointing to the first element
1941 * inserted (or `__position`). In C++98 this returns void.
1942 *
1943 * This function will insert copies of the data in the range
1944 * `[__first,__last)` into the %list before the location specified by
1945 * `__position`.
1946 *
1947 * This operation is linear in the number of elements inserted and
1948 * does not invalidate iterators and references.
1949 */
1950#if __cplusplus201703L >= 201103L
1951 template<typename _InputIterator,
1952 typename = std::_RequireInputIter<_InputIterator>>
1953 iterator
1954 insert(const_iterator __position, _InputIterator __first,
1955 _InputIterator __last);
1956#else
1957 template<typename _InputIterator>
1958 void
1959 insert(iterator __position, _InputIterator __first,
1960 _InputIterator __last)
1961 {
1962 list __tmp(__first, __last, get_allocator());
1963 splice(__position, __tmp);
1964 }
1965#endif
1966
1967#if __glibcxx_containers_ranges // C++ >= 23
1968 /**
1969 * @brief Insert a range into a list.
1970 * @param __position An iterator.
1971 * @param __rg An input range of elements that can be converted to
1972 * the list's value type.
1973 * @return An iterator pointing to the first element inserted,
1974 * or `__position` if the range is empty.
1975 *
1976 * Inserts the elements of `__rg` before `__position`.
1977 * No iterators to existing elements are invalidated by this function.
1978 * If the insertion fails due to an exception, no elements will be added
1979 * and so the list will be unchanged.
1980 *
1981 * @since C++23
1982 */
1983 template<__detail::__container_compatible_range<_Tp> _Rg>
1984 iterator
1985 insert_range(const_iterator __position, _Rg&& __rg)
1986 {
1987 list __tmp(from_range, std::forward<_Rg>(__rg), get_allocator());
1988 if (!__tmp.empty())
1989 {
1990 auto __it = __tmp.begin();
1991 splice(__position, __tmp);
1992 return __it;
1993 }
1994 return __position._M_const_cast();
1995 }
1996#endif
1997
1998 /**
1999 * @brief Remove element at given position.
2000 * @param __position Iterator pointing to element to be erased.
2001 * @return An iterator pointing to the next element (or end()).
2002 *
2003 * This function will erase the element at the given position and thus
2004 * shorten the %list by one.
2005 *
2006 * Due to the nature of a %list this operation can be done in
2007 * constant time, and only invalidates iterators/references to
2008 * the element being removed. The user is also cautioned that
2009 * this function only erases the element, and that if the element
2010 * is itself a pointer, the pointed-to memory is not touched in
2011 * any way. Managing the pointer is the user's responsibility.
2012 */
2013 iterator
2014#if __cplusplus201703L >= 201103L
2015 erase(const_iterator __position) noexcept;
2016#else
2017 erase(iterator __position);
2018#endif
2019
2020 /**
2021 * @brief Remove a range of elements.
2022 * @param __first Iterator pointing to the first element to be erased.
2023 * @param __last Iterator pointing to one past the last element to be
2024 * erased.
2025 * @return An iterator pointing to the element pointed to by @a last
2026 * prior to erasing (or end()).
2027 *
2028 * This function will erase the elements in the range @a
2029 * [first,last) and shorten the %list accordingly.
2030 *
2031 * This operation is linear time in the size of the range and only
2032 * invalidates iterators/references to the element being removed.
2033 * The user is also cautioned that this function only erases the
2034 * elements, and that if the elements themselves are pointers, the
2035 * pointed-to memory is not touched in any way. Managing the pointer
2036 * is the user's responsibility.
2037 */
2038 iterator
2039#if __cplusplus201703L >= 201103L
2040 erase(const_iterator __first, const_iterator __last) noexcept
2041#else
2042 erase(iterator __first, iterator __last)
2043#endif
2044 {
2045 while (__first != __last)
2046 __first = erase(__first);
2047 return __last._M_const_cast();
2048 }
2049
2050 /**
2051 * @brief Swaps data with another %list.
2052 * @param __x A %list of the same element and allocator types.
2053 *
2054 * This exchanges the elements between two lists in constant
2055 * time. Note that the global std::swap() function is
2056 * specialized such that std::swap(l1,l2) will feed to this
2057 * function.
2058 *
2059 * Whether the allocators are swapped depends on the allocator traits.
2060 */
2061 void
2062 swap(list& __x) _GLIBCXX_NOEXCEPTnoexcept
2063 {
2064 _Node_traits::_Node_base::swap(this->_M_impl._M_node,
2065 __x._M_impl._M_node);
2066
2067 size_t __xsize = __x._M_get_size();
2068 __x._M_set_size(this->_M_get_size());
2069 this->_M_set_size(__xsize);
2070
2071 _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(),
2072 __x._M_get_Node_allocator());
2073 }
2074
2075 /**
2076 * Erases all the elements. Note that this function only erases
2077 * the elements, and that if the elements themselves are
2078 * pointers, the pointed-to memory is not touched in any way.
2079 * Managing the pointer is the user's responsibility.
2080 */
2081 void
2082 clear() _GLIBCXX_NOEXCEPTnoexcept
2083 {
2084 _Base::_M_clear();
2085 _Base::_M_init();
2086 }
2087
2088 // [23.2.2.4] list operations
2089 /**
2090 * @brief Insert contents of another %list.
2091 * @param __position Iterator referencing the element to insert before.
2092 * @param __x Source list.
2093 *
2094 * The elements of @a __x are inserted in constant time in front of
2095 * the element referenced by @a __position. @a __x becomes an empty
2096 * list.
2097 *
2098 * Requires this != @a __x.
2099 */
2100 void
2101#if __cplusplus201703L >= 201103L
2102 splice(const_iterator __position, list&& __x) noexcept
2103#else
2104 splice(iterator __position, list& __x)
2105#endif
2106 {
2107 if (!__x.empty())
2108 {
2109 _M_check_equal_allocators(__x);
2110
2111 this->_M_transfer(__position._M_const_cast(),
2112 __x.begin(), __x.end());
2113
2114 this->_M_inc_size(__x._M_get_size());
2115 __x._M_set_size(0);
2116 }
2117 }
2118
2119#if __cplusplus201703L >= 201103L
2120 void
2121 splice(const_iterator __position, list& __x) noexcept
2122 { splice(__position, std::move(__x)); }
2123#endif
2124
2125 /**
2126 * @brief Insert element from another %list.
2127 * @param __position Iterator referencing the element to insert before.
2128 * @param __x Source list.
2129 * @param __i Iterator referencing the element to move.
2130 *
2131 * Removes the element in list @a __x referenced by @a __i and
2132 * inserts it into the current list before @a __position.
2133 *
2134 * @{
2135 */
2136#if __cplusplus201703L >= 201103L
2137 void
2138 splice(const_iterator __position, list&& __x, const_iterator __i) noexcept
2139#else
2140 void
2141 splice(iterator __position, list& __x, iterator __i)
2142#endif
2143 {
2144 iterator __j = __i._M_const_cast();
2145 ++__j;
2146 if (__position == __i || __position == __j)
2147 return;
2148
2149 if (this != std::__addressof(__x))
2150 _M_check_equal_allocators(__x);
2151
2152 this->_M_transfer(__position._M_const_cast(),
2153 __i._M_const_cast(), __j);
2154
2155 this->_M_inc_size(1);
2156 __x._M_dec_size(1);
2157 }
2158
2159#if __cplusplus201703L >= 201103L
2160 void
2161 splice(const_iterator __position, list& __x, const_iterator __i) noexcept
2162 { splice(__position, std::move(__x), __i); }
2163#endif
2164 /// @}
2165
2166 /**
2167 * @brief Insert range from another %list.
2168 * @param __position Iterator referencing the element to insert before.
2169 * @param __x Source list.
2170 * @param __first Iterator referencing the start of range in x.
2171 * @param __last Iterator referencing the end of range in x.
2172 *
2173 * Removes elements in the range [__first,__last) and inserts them
2174 * before @a __position in constant time.
2175 *
2176 * Undefined if @a __position is in [__first,__last).
2177 */
2178#if __cplusplus201703L >= 201103L
2179 void
2180 splice(const_iterator __position, list&& __x, const_iterator __first,
2181 const_iterator __last) noexcept
2182#else
2183 void
2184 splice(iterator __position, list& __x, iterator __first,
2185 iterator __last)
2186#endif
2187 {
2188 if (__first != __last)
2189 {
2190 if (this != std::__addressof(__x))
2191 _M_check_equal_allocators(__x);
2192
2193#if _GLIBCXX_USE_CXX11_ABI1
2194 size_t __n = std::distance(__first, __last);
2195 this->_M_inc_size(__n);
2196 __x._M_dec_size(__n);
2197#endif
2198
2199 this->_M_transfer(__position._M_const_cast(),
2200 __first._M_const_cast(),
2201 __last._M_const_cast());
2202 }
2203 }
2204
2205#if __cplusplus201703L >= 201103L
2206 /**
2207 * @brief Insert range from another %list.
2208 * @param __position Const_iterator referencing the element to
2209 * insert before.
2210 * @param __x Source list.
2211 * @param __first Const_iterator referencing the start of range in x.
2212 * @param __last Const_iterator referencing the end of range in x.
2213 *
2214 * Removes elements in the range [__first,__last) and inserts them
2215 * before @a __position in constant time.
2216 *
2217 * Undefined if @a __position is in [__first,__last).
2218 */
2219 void
2220 splice(const_iterator __position, list& __x, const_iterator __first,
2221 const_iterator __last) noexcept
2222 { splice(__position, std::move(__x), __first, __last); }
2223#endif
2224
2225 private:
2226#ifdef __glibcxx_list_remove_return_type // C++ >= 20 && HOSTED
2227 typedef size_type __remove_return_type;
2228# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG \
2229 __attribute__((__abi_tag__("__cxx20")))
2230#else
2231 typedef void __remove_return_type;
2232# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
2233#endif
2234 public:
2235
2236 /**
2237 * @brief Remove all elements equal to value.
2238 * @param __value The value to remove.
2239 *
2240 * Removes every element in the list equal to @a value.
2241 * Remaining elements stay in list order. Note that this
2242 * function only erases the elements, and that if the elements
2243 * themselves are pointers, the pointed-to memory is not
2244 * touched in any way. Managing the pointer is the user's
2245 * responsibility.
2246 */
2247 _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
2248 __remove_return_type
2249 remove(const _Tp& __value);
2250
2251 /**
2252 * @brief Remove all elements satisfying a predicate.
2253 * @tparam _Predicate Unary predicate function or object.
2254 *
2255 * Removes every element in the list for which the predicate
2256 * returns true. Remaining elements stay in list order. Note
2257 * that this function only erases the elements, and that if the
2258 * elements themselves are pointers, the pointed-to memory is
2259 * not touched in any way. Managing the pointer is the user's
2260 * responsibility.
2261 */
2262 template<typename _Predicate>
2263 __remove_return_type
2264 remove_if(_Predicate);
2265
2266 /**
2267 * @brief Remove consecutive duplicate elements.
2268 *
2269 * For each consecutive set of elements with the same value,
2270 * remove all but the first one. Remaining elements stay in
2271 * list order. Note that this function only erases the
2272 * elements, and that if the elements themselves are pointers,
2273 * the pointed-to memory is not touched in any way. Managing
2274 * the pointer is the user's responsibility.
2275 */
2276 _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
2277 __remove_return_type
2278 unique();
2279
2280 /**
2281 * @brief Remove consecutive elements satisfying a predicate.
2282 * @tparam _BinaryPredicate Binary predicate function or object.
2283 *
2284 * For each consecutive set of elements [first,last) that
2285 * satisfy predicate(first,i) where i is an iterator in
2286 * [first,last), remove all but the first one. Remaining
2287 * elements stay in list order. Note that this function only
2288 * erases the elements, and that if the elements themselves are
2289 * pointers, the pointed-to memory is not touched in any way.
2290 * Managing the pointer is the user's responsibility.
2291 */
2292 template<typename _BinaryPredicate>
2293 __remove_return_type
2294 unique(_BinaryPredicate);
2295
2296#undef _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
2297
2298 /**
2299 * @brief Merge sorted lists.
2300 * @param __x Sorted list to merge.
2301 *
2302 * Assumes that both @a __x and this list are sorted according to
2303 * operator<(). Merges elements of @a __x into this list in
2304 * sorted order, leaving @a __x empty when complete. Elements in
2305 * this list precede elements in @a __x that are equal.
2306 */
2307#if __cplusplus201703L >= 201103L
2308 void
2309 merge(list&& __x);
2310
2311 void
2312 merge(list& __x)
2313 { merge(std::move(__x)); }
2314#else
2315 void
2316 merge(list& __x);
2317#endif
2318
2319 /**
2320 * @brief Merge sorted lists according to comparison function.
2321 * @tparam _StrictWeakOrdering Comparison function defining
2322 * sort order.
2323 * @param __x Sorted list to merge.
2324 * @param __comp Comparison functor.
2325 *
2326 * Assumes that both @a __x and this list are sorted according to
2327 * StrictWeakOrdering. Merges elements of @a __x into this list
2328 * in sorted order, leaving @a __x empty when complete. Elements
2329 * in this list precede elements in @a __x that are equivalent
2330 * according to StrictWeakOrdering().
2331 */
2332#if __cplusplus201703L >= 201103L
2333 template<typename _StrictWeakOrdering>
2334 void
2335 merge(list&& __x, _StrictWeakOrdering __comp);
2336
2337 template<typename _StrictWeakOrdering>
2338 void
2339 merge(list& __x, _StrictWeakOrdering __comp)
2340 { merge(std::move(__x), __comp); }
2341#else
2342 template<typename _StrictWeakOrdering>
2343 void
2344 merge(list& __x, _StrictWeakOrdering __comp);
2345#endif
2346
2347 /**
2348 * @brief Reverse the elements in list.
2349 *
2350 * Reverse the order of elements in the list in linear time.
2351 */
2352 void
2353 reverse() _GLIBCXX_NOEXCEPTnoexcept
2354 { this->_M_impl._M_node._M_reverse(); }
2355
2356 /**
2357 * @brief Sort the elements.
2358 *
2359 * Sorts the elements of this list in NlogN time. Equivalent
2360 * elements remain in list order.
2361 */
2362 void
2363 sort();
2364
2365 /**
2366 * @brief Sort the elements according to comparison function.
2367 *
2368 * Sorts the elements of this list in NlogN time. Equivalent
2369 * elements remain in list order.
2370 */
2371 template<typename _StrictWeakOrdering>
2372 void
2373 sort(_StrictWeakOrdering);
2374
2375 protected:
2376 // Internal constructor functions follow.
2377
2378 // Called by the range constructor to implement [23.1.1]/9
2379
2380 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2381 // 438. Ambiguity in the "do the right thing" clause
2382 template<typename _Integer>
2383 void
2384 _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type)
2385 { _M_fill_initialize(static_cast<size_type>(__n), __x); }
2386
2387 // Called by the range constructor to implement [23.1.1]/9
2388 template<typename _InputIterator>
2389 void
2390 _M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
2391 __false_type)
2392 {
2393 bool __notempty = __first != __last;
2394 for (; __first != __last; ++__first)
2395#if __cplusplus201703L >= 201103L
2396 emplace_back(*__first);
2397#else
2398 push_back(*__first);
2399#endif
2400 if (__notempty)
2401 {
2402 if (begin() == end())
2403 __builtin_unreachable();
2404 }
2405 }
2406
2407 // Called by list(n,v,a), and the range constructor when it turns out
2408 // to be the same thing.
2409 void
2410 _M_fill_initialize(size_type __n, const value_type& __x)
2411 {
2412 for (; __n; --__n)
2413 push_back(__x);
2414 }
2415
2416#if __cplusplus201703L >= 201103L
2417 // Called by list(n).
2418 void
2419 _M_default_initialize(size_type __n)
2420 {
2421 for (; __n; --__n)
2422 emplace_back();
2423 }
2424
2425 // Called by resize(sz).
2426 void
2427 _M_default_append(size_type __n);
2428#endif
2429
2430 // Internal assign functions follow.
2431
2432 // Called by the range assign to implement [23.1.1]/9
2433
2434 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2435 // 438. Ambiguity in the "do the right thing" clause
2436 template<typename _Integer>
2437 void
2438 _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
2439 { _M_fill_assign(__n, __val); }
2440
2441 // Called by the range assign to implement [23.1.1]/9
2442 template<typename _InputIterator>
2443 void
2444 _M_assign_dispatch(_InputIterator __first, _InputIterator __last,
2445 __false_type);
2446
2447 // Called by assign(n,t), and the range assign when it turns out
2448 // to be the same thing.
2449 void
2450 _M_fill_assign(size_type __n, const value_type& __val);
2451
2452
2453 // Moves the elements from [first,last) before position.
2454 void
2455 _M_transfer(iterator __position, iterator __first, iterator __last)
2456 { __position._M_node->_M_transfer(__first._M_node, __last._M_node); }
2457
2458 // Inserts new element at position given and with value given.
2459#if __cplusplus201703L < 201103L
2460 void
2461 _M_insert(iterator __position, const value_type& __x)
2462 {
2463 _Node_ptr __tmp = _M_create_node(__x);
2464 __tmp->_M_hook(__position._M_node);
2465 this->_M_inc_size(1);
2466 }
2467#else
2468 template<typename... _Args>
2469 void
2470 _M_insert(iterator __position, _Args&&... __args)
2471 {
2472 _Node_ptr __tmp = _M_create_node(std::forward<_Args>(__args)...);
2473 __tmp->_M_hook(__position._M_node);
2474 this->_M_inc_size(1);
2475 }
2476#endif
2477
2478 // Erases element at position given.
2479 void
2480 _M_erase(iterator __position) _GLIBCXX_NOEXCEPTnoexcept
2481 {
2482 typedef typename _Node_traits::_Node _Node;
2483 this->_M_dec_size(1);
2484 __position._M_node->_M_unhook();
2485 _Node& __n = static_cast<_Node&>(*__position._M_node);
2486 this->_M_destroy_node(__n._M_node_ptr());
2487 }
2488
2489 // To implement the splice (and merge) bits of N1599.
2490 void
2491 _M_check_equal_allocators(const list& __x) _GLIBCXX_NOEXCEPTnoexcept
2492 {
2493 if (_M_get_Node_allocator() != __x._M_get_Node_allocator())
2494 __builtin_abort();
2495 }
2496
2497 // Used to implement resize.
2498 const_iterator
2499 _M_resize_pos(size_type& __new_size) const;
2500
2501#if __cplusplus201703L >= 201103L && ! _GLIBCXX_INLINE_VERSION0
2502 // XXX GLIBCXX_ABI Deprecated
2503 // These are unused and only kept so that explicit instantiations will
2504 // continue to define the symbols.
2505 void
2506 _M_move_assign(list&& __x, true_type) noexcept
2507 {
2508 this->clear();
2509 this->_M_move_nodes(std::move(__x));
2510 std::__alloc_on_move(this->_M_get_Node_allocator(),
2511 __x._M_get_Node_allocator());
2512 }
2513
2514 void
2515 _M_move_assign(list&& __x, false_type)
2516 {
2517 if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator())
2518 _M_move_assign(std::move(__x), true_type{});
2519 else
2520 // The rvalue's allocator cannot be moved, or is not equal,
2521 // so we need to individually move each element.
2522 _M_assign_dispatch(std::make_move_iterator(__x.begin()),
2523 std::make_move_iterator(__x.end()),
2524 __false_type{});
2525 }
2526#endif
2527
2528#if _GLIBCXX_USE_CXX11_ABI1
2529 // Update _M_size members after merging (some of) __src into __dest.
2530 struct _Finalize_merge
2531 {
2532 explicit
2533 _Finalize_merge(list& __dest, list& __src, const iterator& __src_next)
2534 : _M_dest(__dest), _M_src(__src), _M_next(__src_next)
2535 { }
2536
2537 ~_Finalize_merge()
2538 {
2539 // For the common case, _M_next == _M_sec.end() and the std::distance
2540 // call is fast. But if any *iter1 < *iter2 comparison throws then we
2541 // have to count how many elements remain in _M_src.
2542 const size_t __num_unmerged = std::distance(_M_next, _M_src.end());
2543 const size_t __orig_size = _M_src._M_get_size();
2544 _M_dest._M_inc_size(__orig_size - __num_unmerged);
2545 _M_src._M_set_size(__num_unmerged);
2546 }
2547
2548 list& _M_dest;
2549 list& _M_src;
2550 const iterator& _M_next;
2551
2552#if __cplusplus201703L >= 201103L
2553 _Finalize_merge(const _Finalize_merge&) = delete;
2554#endif
2555 };
2556#else
2557 struct _Finalize_merge
2558 { explicit _Finalize_merge(list&, list&, const iterator&) { } };
2559#endif
2560
2561#if !_GLIBCXX_INLINE_VERSION0
2562 // XXX GLIBCXX_ABI Deprecated
2563 // These members are unused by std::list now, but we keep them here
2564 // so that an explicit instantiation of std::list will define them.
2565 // This ensures that any objects or libraries compiled against old
2566 // versions of GCC will still be able to use the symbols.
2567
2568#if _GLIBCXX_USE_CXX11_ABI1
2569 static size_t
2570 _S_distance(const_iterator __first, const_iterator __last)
2571 { return std::distance(__first, __last); }
2572
2573 size_t
2574 _M_node_count() const
2575 { return this->_M_get_size(); }
2576#else
2577 static size_t
2578 _S_distance(const_iterator, const_iterator)
2579 { return 0; }
2580
2581 size_t
2582 _M_node_count() const
2583 { return std::distance(begin(), end()); }
2584#endif
2585#endif // ! INLINE_VERSION
2586 };
2587
2588#if __cpp_deduction_guides201703L >= 201606
2589 template<typename _InputIterator, typename _ValT
2590 = typename iterator_traits<_InputIterator>::value_type,
2591 typename _Allocator = allocator<_ValT>,
2592 typename = _RequireInputIter<_InputIterator>,
2593 typename = _RequireAllocator<_Allocator>>
2594 list(_InputIterator, _InputIterator, _Allocator = _Allocator())
2595 -> list<_ValT, _Allocator>;
2596
2597#if __glibcxx_containers_ranges // C++ >= 23
2598 template<ranges::input_range _Rg,
2599 typename _Allocator = allocator<ranges::range_value_t<_Rg>>>
2600 list(from_range_t, _Rg&&, _Allocator = _Allocator())
2601 -> list<ranges::range_value_t<_Rg>, _Allocator>;
2602#endif
2603#endif
2604
2605_GLIBCXX_END_NAMESPACE_CXX11}
2606
2607 /**
2608 * @brief List equality comparison.
2609 * @param __x A %list.
2610 * @param __y A %list of the same type as @a __x.
2611 * @return True iff the size and elements of the lists are equal.
2612 *
2613 * This is an equivalence relation. It is linear in the size of
2614 * the lists. Lists are considered equivalent if their sizes are
2615 * equal, and if corresponding elements compare equal.
2616 */
2617 template<typename _Tp, typename _Alloc>
2618 _GLIBCXX_NODISCARD[[__nodiscard__]]
2619 inline bool
2620 operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2621 {
2622#if _GLIBCXX_USE_CXX11_ABI1
2623 if (__x.size() != __y.size())
2624 return false;
2625#endif
2626
2627 typedef typename list<_Tp, _Alloc>::const_iterator const_iterator;
2628 const_iterator __end1 = __x.end();
2629 const_iterator __end2 = __y.end();
2630
2631 const_iterator __i1 = __x.begin();
2632 const_iterator __i2 = __y.begin();
2633 while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2)
2634 {
2635 ++__i1;
2636 ++__i2;
2637 }
2638 return __i1 == __end1 && __i2 == __end2;
2639 }
2640
2641#if __cpp_lib_three_way_comparison
2642/**
2643 * @brief List ordering relation.
2644 * @param __x A `list`.
2645 * @param __y A `list` of the same type as `__x`.
2646 * @return A value indicating whether `__x` is less than, equal to,
2647 * greater than, or incomparable with `__y`.
2648 *
2649 * See `std::lexicographical_compare_three_way()` for how the determination
2650 * is made. This operator is used to synthesize relational operators like
2651 * `<` and `>=` etc.
2652 */
2653 template<typename _Tp, typename _Alloc>
2654 [[nodiscard]]
2655 inline __detail::__synth3way_t<_Tp>
2656 operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2657 {
2658 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
2659 __y.begin(), __y.end(),
2660 __detail::__synth3way);
2661 }
2662#else
2663 /**
2664 * @brief List ordering relation.
2665 * @param __x A %list.
2666 * @param __y A %list of the same type as @a __x.
2667 * @return True iff @a __x is lexicographically less than @a __y.
2668 *
2669 * This is a total ordering relation. It is linear in the size of the
2670 * lists. The elements must be comparable with @c <.
2671 *
2672 * See std::lexicographical_compare() for how the determination is made.
2673 */
2674 template<typename _Tp, typename _Alloc>
2675 _GLIBCXX_NODISCARD[[__nodiscard__]]
2676 inline bool
2677 operator<(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2678 { return std::lexicographical_compare(__x.begin(), __x.end(),
2679 __y.begin(), __y.end()); }
2680
2681 /// Based on operator==
2682 template<typename _Tp, typename _Alloc>
2683 _GLIBCXX_NODISCARD[[__nodiscard__]]
2684 inline bool
2685 operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2686 { return !(__x == __y); }
2687
2688 /// Based on operator<
2689 template<typename _Tp, typename _Alloc>
2690 _GLIBCXX_NODISCARD[[__nodiscard__]]
2691 inline bool
2692 operator>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2693 { return __y < __x; }
2694
2695 /// Based on operator<
2696 template<typename _Tp, typename _Alloc>
2697 _GLIBCXX_NODISCARD[[__nodiscard__]]
2698 inline bool
2699 operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2700 { return !(__y < __x); }
2701
2702 /// Based on operator<
2703 template<typename _Tp, typename _Alloc>
2704 _GLIBCXX_NODISCARD[[__nodiscard__]]
2705 inline bool
2706 operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2707 { return !(__x < __y); }
2708#endif // three-way comparison
2709
2710 /// See std::list::swap().
2711 template<typename _Tp, typename _Alloc>
2712 inline void
2713 swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
2714 _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))noexcept(noexcept(__x.swap(__y)))
2715 { __x.swap(__y); }
2716
2717_GLIBCXX_END_NAMESPACE_CONTAINER
2718
2719#if _GLIBCXX_USE_CXX11_ABI1
2720
2721 // Detect when distance is used to compute the size of the whole list.
2722 template<typename _Tp>
2723 inline ptrdiff_t
2724 __distance(_GLIBCXX_STD_Cstd::_List_iterator<_Tp> __first,
2725 _GLIBCXX_STD_Cstd::_List_iterator<_Tp> __last,
2726 input_iterator_tag __tag)
2727 {
2728 typedef _GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> _CIter;
2729 return std::__distance(_CIter(__first), _CIter(__last), __tag);
2730 }
2731
2732 template<typename _Tp>
2733 inline ptrdiff_t
2734 __distance(_GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> __first,
2735 _GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> __last,
2736 input_iterator_tag)
2737 {
2738 typedef __detail::_List_node_header _Sentinel;
2739 _GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> __beyond = __last;
2740 ++__beyond;
2741 const bool __whole = __first == __beyond;
2742 if (__builtin_constant_p (__whole) && __whole)
2743 return static_cast<const _Sentinel*>(__last._M_node)->_M_size;
2744
2745 ptrdiff_t __n = 0;
2746 while (__first != __last)
2747 {
2748 ++__first;
2749 ++__n;
2750 }
2751 return __n;
2752 }
2753
2754#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
2755 template<bool _Const, typename _Ptr>
2756 inline ptrdiff_t
2757 __distance(__list::_Iterator<_Const, _Ptr> __first,
2758 __list::_Iterator<_Const, _Ptr> __last,
2759 input_iterator_tag __tag)
2760 {
2761 using _Tp = typename __list::_Iterator<_Const, _Ptr>::value_type;
2762 using _Sentinel = typename __list::_Node_traits<_Tp, _Ptr>::_Node_header;
2763 auto __beyond = __last;
2764 ++__beyond;
2765 const bool __whole = __first == __beyond;
2766 if (__builtin_constant_p (__whole) && __whole)
2767 return static_cast<const _Sentinel&>(*__last._M_node)._M_size;
2768
2769 ptrdiff_t __n = 0;
2770 while (__first != __last)
2771 {
2772 ++__first;
2773 ++__n;
2774 }
2775 return __n;
2776 }
2777#endif
2778#endif
2779
2780#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST1
2781namespace __list
2782{
2783 template<typename _VoidPtr>
2784 void
2785 _Node_base<_VoidPtr>::swap(_Node_base& __x, _Node_base& __y) noexcept
2786 {
2787 auto __px = __x._M_base();
2788 auto __py = __x._M_base();
2789
2790 if (__x._M_next != __px)
2791 {
2792 if (__y._M_next != __py)
2793 {
2794 using std::swap;
2795 // Both __x and __y are not empty.
2796 swap(__x._M_next,__y._M_next);
2797 swap(__x._M_prev,__y._M_prev);
2798 __x._M_next->_M_prev = __x._M_prev->_M_next = __px;
2799 __y._M_next->_M_prev = __y._M_prev->_M_next = __py;
2800 }
2801 else
2802 {
2803 // __x is not empty, __y is empty.
2804 __y._M_next = __x._M_next;
2805 __y._M_prev = __x._M_prev;
2806 __y._M_next->_M_prev = __y._M_prev->_M_next = __py;
2807 __x._M_next = __x._M_prev = __px;
2808 }
2809 }
2810 else if (__y._M_next != __py)
2811 {
2812 // __x is empty, __y is not empty.
2813 __x._M_next = __y._M_next;
2814 __x._M_prev = __y._M_prev;
2815 __x._M_next->_M_prev = __x._M_prev->_M_next = __px;
2816 __y._M_next = __y._M_prev = __py;
2817 }
2818 }
2819
2820 template<typename _VoidPtr>
2821 void
2822 _Node_base<_VoidPtr>::_M_transfer(_Base_ptr const __first,
2823 _Base_ptr const __last) noexcept
2824 {
2825 __glibcxx_assert(__first != __last)do { if (std::__is_constant_evaluated() && !bool(__first
!= __last)) std::__glibcxx_assert_fail(); } while (false)
;
2826
2827 auto __self = _M_base();
2828 if (__self != __last)
2829 {
2830 // Remove [first, last) from its old position.
2831 __last->_M_prev->_M_next = __self;
2832 __first->_M_prev->_M_next = __last;
2833 this->_M_prev->_M_next = __first;
2834
2835 // Splice [first, last) into its new position.
2836 auto const __tmp = this->_M_prev;
2837 this->_M_prev = __last->_M_prev;
2838 __last->_M_prev = __first->_M_prev;
2839 __first->_M_prev = __tmp;
2840 }
2841 }
2842
2843 template<typename _VoidPtr>
2844 void
2845 _Node_header<_VoidPtr>::_M_reverse() noexcept
2846 {
2847 const auto __self = this->_M_base();
2848 auto __tmp = __self;
2849 do
2850 {
2851 using std::swap;
2852 swap(__tmp->_M_next, __tmp->_M_prev);
2853
2854 // Old next node is now prev.
2855 __tmp = __tmp->_M_prev;
2856 }
2857 while (__tmp != __self);
2858 }
2859} // namespace __list
2860#endif
2861
2862_GLIBCXX_END_NAMESPACE_VERSION
2863} // namespace std
2864
2865#endif /* _STL_LIST_H */

←

ui/dock_widgets/property_sheet/metaentity/lc_entity_type_propertiesprovider.h

→
1/*
2 * ********************************************************************************
3 * This file is part of the LibreCAD project, a 2D CAD program
4 *
5 * Copyright (C) 2025 LibreCAD.org
6 * Copyright (C) 2025 sand1024
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * ********************************************************************************
22 */
23
24#ifndef LC_ENTITYTYPEPROPERTIESPROVIDER_H
25#define LC_ENTITYTYPEPROPERTIESPROVIDER_H
26
27#include "lc_entitypropertyvaluedelegate.h"
28#include "lc_formatter.h"
29#include "lc_linemath.h"
30#include "lc_property_bool_checkbox_view.h"
31#include "lc_property_container.h"
32#include "lc_property_container_builder.h"
33#include "lc_property_enum.h"
34#include "lc_property_int.h"
35#include "lc_property_int_spinbox_view.h"
36#include "lc_property_qstring.h"
37#include "lc_property_qstring_lineedit_view.h"
38#include "lc_property_qstring_font_combobox_view.h"
39#include "lc_property_qstring_list_combobox_view.h"
40#include "lc_property_rsvector.h"
41#include "lc_propertyprovider_utils.h"
42#include "lc_propertysheetwidget.h"
43#include "rs.h"
44#include "rs_entity.h"
45
46class LC_EnumDescriptor;
47class LC_PropertySheetWidget;
48class LC_ActionContext;
49class RS_Document;
50
51class LC_EntityTypePropertiesProvider : public LC_PropertyContainerBuilder {
52 Q_OBJECTpublic: clang diagnostic push clang diagnostic ignored "-Winconsistent-missing-override"
clang diagnostic ignored "-Wsuggest-override" static const
QMetaObject staticMetaObject; virtual const QMetaObject *metaObject
() const; virtual void *qt_metacast(const char *); virtual int
qt_metacall(QMetaObject::Call, int, void **); static inline QString
tr(const char *s, const char *c = nullptr, int n = -1) { return
staticMetaObject.tr(s, c, n); } private: template <typename
> static constexpr auto qt_create_metaobjectdata(); template
<typename MetaObjectTagType> static constexpr inline auto
qt_staticMetaObjectContent = qt_create_metaobjectdata<MetaObjectTagType
>(); template <typename MetaObjectTagType> static constexpr
inline auto qt_staticMetaObjectStaticContent = qt_staticMetaObjectContent
<MetaObjectTagType>.staticData; template <typename MetaObjectTagType
> static constexpr inline auto qt_staticMetaObjectRelocatingContent
= qt_staticMetaObjectContent<MetaObjectTagType>.relocatingData
; __attribute__((visibility("hidden"))) static void qt_static_metacall
(QObject *, QMetaObject::Call, int, void **); struct QPrivateSignal
{ explicit QPrivateSignal () = default; }; clang diagnostic pop
public:
53 using FunCreateGenericProperty = typename std::function<void(const LC_Property::Names& names, RS_Entity* entity,
54 LC_PropertyContainer* container, QList<LC_PropertyAtomic*>*)>;
55
56 LC_EntityTypePropertiesProvider(const RS2::EntityType entityType, LC_ActionContext* actionContext, LC_PropertySheetWidget* widget)
57 : LC_PropertyContainerBuilder(actionContext,widget), m_entityType{entityType} {
58 }
59
60 static const QString SECTION_GENERAL;
61 static const QString SECTION_GEOMETRY;
62 static const QString SECTION_CALCULATED_INFO;
63 static const QString SECTION_SINGLE_ENTITY_ACTIONS;
64 static const QString SECTION_MULTI_ENTITY_ACTIONS;
65 static const QString SECTION_TEXT;
66 static const QString SECTION_TOOL_OPTIONS;
67 static const QString SECTION_SNAP_TOOL_OPTIONS;
68
69 void fillEntityProperties(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
70protected:
71
72 RS2::EntityType m_entityType;
73
74 virtual void fillSelectedSetCommands(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
75 virtual void fillComputedProperites(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
76 virtual void fillSingleEntityCommands(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
77
78 virtual void doCreateCalculatedProperties([[maybe_unused]]LC_PropertyContainer* container, [[maybe_unused]]const QList<RS_Entity*>& list) {}
79 virtual void doCreateSingleEntityCommands(LC_PropertyContainer* cont, RS_Entity* entity);
80 virtual void doCreateEntitySpecificProperties(LC_PropertyContainer* container, const QList<RS_Entity*>& list) = 0;
81 virtual void doCreateSelectedSetCommands(LC_PropertyContainer* propertyContainer, const QList<RS_Entity*>& list);
82
83
84 bool isShowLinks() const {
85 return m_widget->getOptions()->showLinks;
86 }
87
88 bool isShowSingleEntitySection() const {
89 return m_widget->getOptions()->showSingleEntityCommands;
90 }
91
92 bool isShowComputedSection() const {
93 return m_widget->getOptions()->showComputed;
94 }
95
96 template <typename EntityType>
97 void add(const LC_Property::Names& names,
98 std::function<void(const LC_Property::Names& names, EntityType* entity, LC_PropertyContainer* container,
99 QList<LC_PropertyAtomic*>*)> propertyInit, const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
100
101 template <class ValueType, class EntityClass>
102 void createDelegatedStorage(typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueGet funGet,
103 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueSetShort funSet,
104 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueEqual funEqual,
105 EntityClass* entity, LC_PropertySingle<ValueType>* property);
106
107 template <class EntityClass>
108 void createEntityContextCommand(LC_PropertyContainer* container, const QString& propertyName, RS2::ActionType actionType,
109 const QString& linkTitle, const QString& linkTooltip, RS2::ActionType actionTypeRight,
110 const QString& linkTitleRight, const QString& linkTooltipRight, EntityClass* entity, const QString& commonDescription,
111 bool setContextEntity = true);
112
113
114
115 template <class EntityClass>
116 void createEntityContextCommands(const std::list<CommandLinkInfo>& links, LC_PropertyContainer* container, EntityClass* entity, const QString& namePrefix, bool setContextEntity = true);
117
118
119 template <class EntityClass>
120 void doCreateDelegatedVector(const LC_Property::Names& names,
121 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
122 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueSetShort funSet,
123 RS2::EntityType entityType, const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
124
125 void addCommon(const LC_Property::Names& names, const FunCreateGenericProperty& propertyInit, const QList<RS_Entity*>& list,
126 LC_PropertyContainer* cont);
127
128 void addMultipleProperties(LC_PropertyContainer* cont, QList<LC_PropertyAtomic*> props);
129
130 void fillGenericAttributes(LC_PropertyContainer* container, const QList<RS_Entity*>& list);
131
132 template <typename EntityClass>
133 void addVector(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
134 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
135 LC_PropertyContainer* cont) {
136 doCreateDelegatedVector<EntityClass>(names, funGet, funSet, m_entityType, list, cont);
137 }
138
139 template <typename EntityClass>
140 void addReadOnlyVector(const LC_Property::Names& names,
141 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
142 const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
143
144 template <typename EntityClass>
145 void addLinearDistance(const LC_Property::Names& names,
146 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
147 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
148 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
149 std::function<void(LC_PropertyViewDescriptor*)> funFillViewAttrs = nullptr);
150
151 template <typename EntityClass>
152 void addDouble(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
153 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
154 LC_PropertyContainer* cont, std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funFillViewAttrs = nullptr);
155
156 template <typename EntityClass>
157 void addWCSAngle(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
158 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
159 LC_PropertyContainer* cont);
160
161 template <typename EntityClass>
162 void addRawAngle(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
163 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
164 LC_PropertyContainer* cont);
165
166 template <typename EntityClass>
167 void addBoolean(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueGet funGet,
168 typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
169 LC_PropertyContainer* cont, const QString& viewName = LC_PropertyBoolCheckBoxView::VIEW_NAME,
170 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funPrepareDescriptor = nullptr);
171
172 template <typename EntityClass>
173 void addStringList(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
174 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
175 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funFillList,
176 // fixme - this may be expanded to support item icon, display name and data + change in View
177 const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
178
179 template <class EntityClass>
180 void addStringFont(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
181 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
182 const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
183
184 template <class EntityClass>
185 void addString(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
186 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
187 LC_PropertyContainer* cont, bool multiLine,
188 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funPrepareDescriptor = nullptr);
189
190 template <typename EntityClass>
191 void addIntSpinbox(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueGet funGet,
192 typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
193 LC_PropertyContainer* cont, int minVal = 1, int maxVal = -1);
194
195 template <typename EntityClass>
196 void addEnum(const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
197 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet funGetValue,
198 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
199 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
200 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funPrepareDescriptor = nullptr);
201
202 template <typename EntityClass>
203 void addVarEnum(const LC_Property::Names& names, std::function<LC_EnumDescriptor*(EntityClass*)> funEnumDescriptorProvider,
204 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet funGetValue,
205 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
206 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
207 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funPrepareDescriptor = nullptr);
208
209 template <typename EntityClass>
210 void addReadOnlyString(const LC_Property::Names& names, std::function<QString(EntityClass*)> funValue, const QList<RS_Entity*>& list,
211 LC_PropertyContainer* cont, bool copyable = false);
212
213 LC_PropertyContainer* createGeometrySection(LC_PropertyContainer* container) const;
214 LC_PropertyContainer* createTextContainer(LC_PropertyContainer* container) const;
215 LC_PropertyContainer* createCalculatedInfoSection(LC_PropertyContainer* container) const;
216 LC_PropertyContainer* createSingleEntityActionsSection(LC_PropertyContainer* container) const;
217 LC_PropertyContainer* createMultipleEntityActionsSection(LC_PropertyContainer* container) const;
218};
219
220template <typename EntityType>
221void LC_EntityTypePropertiesProvider::add(const LC_Property::Names& names,
222 std::function<void(const LC_Property::Names& names, EntityType* entity,
223 LC_PropertyContainer* container, QList<LC_PropertyAtomic*>*)> propertyInit,
224 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
225 QList<LC_PropertyAtomic*> props;
226 props.reserve(list.size());
227 for (const auto entity : list) {
228 if (entity->rtti() != m_entityType) {
229 continue;
230 }
231 auto typedEntity = static_cast<EntityType*>(entity);
232 propertyInit(names, typedEntity, cont, &props);
233 }
234 addMultipleProperties(cont, props);
235}
236
237template <typename EntityClass>
238void LC_EntityTypePropertiesProvider::addLinearDistance(const LC_Property::Names& names,
239 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
240 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort
241 funSet, const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
242 std::function<void(LC_PropertyViewDescriptor*)> funFillViewAttrs) {
243 add<EntityClass>(names, [this, funGet, funSet,funFillViewAttrs](const LC_Property::Names& n, EntityClass* entity,
244 LC_PropertyContainer* container,
245 QList<LC_PropertyAtomic*>* props) -> void {
246 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::DISTANCE,
247 m_actionContext, m_widget);
248 if (funFillViewAttrs != nullptr) {
249 LC_PropertyViewDescriptor descriptor;
250 funFillViewAttrs(&descriptor);
251 property->setViewDescriptor(descriptor);
252 }
253
254 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
255 property->setValueStorage(valueStorage, true);
256 valueStorage->setup(entity, m_widget, funGet, funSet, [funGet](const double& v, EntityClass* e) -> bool {
257 return LC_LineMath::isSameLength(v, funGet(e));
258 });
259 }, list, cont);
260}
261
262template <typename EntityClass>
263void LC_EntityTypePropertiesProvider::addDouble(const LC_Property::Names& names,
264 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
265 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
266 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
267 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funFillViewAttrs) {
268 add<EntityClass>(names, [this, funGet, funSet,funFillViewAttrs](const LC_Property::Names& n, EntityClass* entity,
269 LC_PropertyContainer* container,
270 QList<LC_PropertyAtomic*>* props) -> void {
271 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::NOTNEEDED,
272 m_actionContext, m_widget);
273 bool readonly = false;
274 if (funFillViewAttrs != nullptr) {
275 LC_PropertyViewDescriptor descriptor;
276 readonly = funFillViewAttrs(entity, descriptor);
277 property->setViewDescriptor(descriptor);
278 }
279
280 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
281 property->setValueStorage(valueStorage, true);
282 valueStorage->setup(entity, m_widget, funGet, funSet, [funGet](const double& v, EntityClass* e) -> bool {
283 return LC_LineMath::isSameLength(v, funGet(e));
284 });
285 if (readonly || funSet == nullptr) {
286 property->setReadOnly();
287 }
288 }, list, cont);
289}
290
291template <typename EntityClass>
292void LC_EntityTypePropertiesProvider::addBoolean(const LC_Property::Names& names,
293 typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueGet funGet,
294 typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueSetShort funSet,
295 const QList<RS_Entity*>& list, LC_PropertyContainer* cont, const QString& viewName,
296 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)>
297 funPrepareDescriptor) {
298 add<EntityClass>(names, [this, funGet, funSet, viewName,funPrepareDescriptor](const LC_Property::Names& n, EntityClass* entity,
299 LC_PropertyContainer* container,
300 QList<LC_PropertyAtomic*>* props) -> void {
301 auto property = new LC_PropertyBool(container, false);
302 property->setNames(n);
303
304 LC_PropertyViewDescriptor descriptor(viewName.toLatin1());
305 bool readOnly = false;
306 if (funPrepareDescriptor != nullptr) {
307 readOnly = funPrepareDescriptor(entity, descriptor);
308 }
309 property->setViewDescriptor(descriptor);
310 props->push_back(property);
311 createDelegatedStorage<bool, EntityClass>(funGet, funSet, [funGet](bool& v, EntityClass* e) -> bool {
312 return v == funGet(e);
313 }, entity, property);
314 if (funSet == nullptr || readOnly) {
315 property->setReadOnly();
316 }
317 }, list, cont);
318}
319
320template <typename EntityClass>
321void LC_EntityTypePropertiesProvider::addReadOnlyString(const LC_Property::Names& names, std::function<QString(EntityClass*)> funValue,
322 const QList<RS_Entity*>& list, LC_PropertyContainer* cont, const bool copyable) {
323 add<EntityClass>(names, [this, funValue, copyable](const LC_Property::Names& n, EntityClass* e, LC_PropertyContainer* container,
324 QList<LC_PropertyAtomic*>* props) -> void {
325 const QString value = funValue(e);
326 auto* property = createReadonlyStringProperty(n, props, container, value);
327 if (copyable) {
328 LC_PropertyViewDescriptor descriptor(LC_PropertyQStringLineEditView::VIEW_NAME);
329 descriptor[LC_PropertyQStringLineEditView::ATTR_COPYABLE_READ_ONLY] = true;
330 descriptor[LC_PropertyQStringLineEditView::ATTR_PLACEHOLDER] = tr("Unavailable");
331 property->setViewDescriptor(descriptor);
332 }
333 }, list, cont);
334}
335
336template <typename EntityClass>
337void LC_EntityTypePropertiesProvider::addStringList(const LC_Property::Names& names,
338 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
339 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
340 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funFillList,
341 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
342 add<EntityClass>(names, [this, funFillList, funGet, funSet](const LC_Property::Names& n, EntityClass* entity,
343 LC_PropertyContainer* container, QList<LC_PropertyAtomic*>* props) -> void {
344 auto property = new LC_PropertyQString(container, false);
345 property->setNames(n);
346 LC_PropertyViewDescriptor descriptor(LC_PropertyQStringListComboBoxView::VIEW_NAME);
347 bool readonly = funFillList(entity, descriptor);
348 property->setViewDescriptor(descriptor);
349 props->push_back(property);
350 createDelegatedStorage<QString, EntityClass>(funGet, funSet, [funGet](QString& v, EntityClass* e) -> bool {
351 return v == funGet(e);
352 }, entity, property);
353 if (readonly || funSet == nullptr) {
354 property->setReadOnly();
355 }
356 }, list, cont);
357}
358
359template <typename EntityClass>
360void LC_EntityTypePropertiesProvider::addStringFont(const LC_Property::Names& names,
361 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
362 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
363 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
364 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
365 QList<LC_PropertyAtomic*>* props) -> void {
366 auto property = new LC_PropertyQString(container, false);
367 property->setNames(n);
368 LC_PropertyViewDescriptor viewDescriptor;
369 viewDescriptor.viewName = LC_PropertyQStringFontComboboxView::VIEW_NAME;
370 property->setViewDescriptor(viewDescriptor);
371 props->push_back(property);
372
373 auto valueStorage = new LC_EntityPropertyValueDelegate<QString, EntityClass>();
374 property->setValueStorage(valueStorage, true);
375 valueStorage->setup(entity, this->m_widget, funGet, funSet, [funGet](QString& v, EntityClass* e) -> bool {
376 return v == funGet(e);
377 });
378 }, list, cont);
379}
380
381template <typename EntityClass>
382void LC_EntityTypePropertiesProvider::addString(const LC_Property::Names& names,
383 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
384 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
385 const QList<RS_Entity*>& list, LC_PropertyContainer* cont, bool multiLine,
386 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funPrepareDescriptor) {
387 add<EntityClass>(names, [this, funGet, funSet, multiLine, funPrepareDescriptor](const LC_Property::Names& n, EntityClass* entity,
388 LC_PropertyContainer* container,
389 QList<LC_PropertyAtomic*>* props) -> void {
390 auto property = new LC_PropertyQString(container, false);
391 property->setNames(n);
392 LC_PropertyViewDescriptor viewDescriptor;
393 viewDescriptor.viewName = LC_PropertyQStringLineEditView::VIEW_NAME;
394 viewDescriptor.attributes[LC_PropertyQStringLineEditView::ATTR_MULTILINE_EDIT] = multiLine;
395 property->setViewDescriptor(viewDescriptor);
396 props->push_back(property);
397
398 auto valueStorage = new LC_EntityPropertyValueDelegate<QString, EntityClass>();
399 property->setValueStorage(valueStorage, true);
400 valueStorage->setup(entity, this->m_widget, funGet, funSet, [funGet](QString& v, EntityClass* e) -> bool {
401 return v == funGet(e);
402 });
403
404 bool readonly = false;
405 if (funPrepareDescriptor != nullptr) {
406 readonly = funPrepareDescriptor(entity, viewDescriptor);
407 }
408 if (readonly || funSet == nullptr) {
409 property->setReadOnly();
410 }
411 }, list, cont);
412}
413
414template <typename EntityClass>
415void LC_EntityTypePropertiesProvider::addWCSAngle(const LC_Property::Names& names,
416 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
417 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
418 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
419 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
420 QList<LC_PropertyAtomic*>* props) -> void {
421 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::ANGLE, m_actionContext,
422 m_widget);
423 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
424 valueStorage->setup(entity, m_widget, [this, funGet](EntityClass* e) -> double {
425 const double wcsAngle = funGet(e);
426 const double ucsAngle = toUCSBasisAngle(wcsAngle); // here we return in UCS for editing*/
427 return ucsAngle;
428 }, (funSet != nullptr)
429 ? [this, funSet](const double& value,
430 EntityClass* e) -> void {
431 // here we expect value in radians and in ucs
432 const double ucsBasisAngle = value;
433 double wcsAngle = toWCSAngle(ucsBasisAngle);
434 funSet(wcsAngle, e);
435 }
436 : funSet, [funGet](const double& v, EntityClass* e) -> bool {
437 return LC_LineMath::isSameAngle(v, funGet(e));
438 });
439 if (funSet == nullptr) {
440 property->setReadOnly();
441 }
442 property->setValueStorage(valueStorage, true);
443 }, list, cont);
444}
445
446template <typename EntityClass>
447void LC_EntityTypePropertiesProvider::addRawAngle(const LC_Property::Names& names,
448 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
449 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
450 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
451 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
452 QList<LC_PropertyAtomic*>* props) -> void {
453 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::ANGLE, m_actionContext,
454 m_widget);
455 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
456 valueStorage->setup(entity, m_widget, funGet, funSet, [funGet](const double& v, EntityClass* e) -> bool {
457 return LC_LineMath::isSameAngle(v, funGet(e));
458 });
459 property->setValueStorage(valueStorage, true);
460 }, list, cont);
461}
462
463template <typename EntityClass>
464void LC_EntityTypePropertiesProvider::addReadOnlyVector(const LC_Property::Names& names,
465 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
466 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
467 add<EntityClass>(names, [this, funGet](const LC_Property::Names& n, EntityClass* e, LC_PropertyContainer* container,
468 QList<LC_PropertyAtomic*>* props) -> void {
469 auto property = createVectorProperty(n, props, container, m_actionContext, m_widget);
470 auto valueStorage = new LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>();
471 property->setValueStorage(valueStorage, true);
472 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueSetShort funSet = nullptr;
473 valueStorage->setup(e, m_widget, funGet, funSet, nullptr);
474 property->setReadOnly();
475 }, list, cont);
476}
477
478template <typename EntityClass>
479void LC_EntityTypePropertiesProvider::doCreateDelegatedVector(const LC_Property::Names& names,
480 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet
481 funGet,
482 typename LC_EntityPropertyValueDelegate<
483 RS_Vector, EntityClass>::FunValueSetShort funSet,
484 [[maybe_unused]] RS2::EntityType entityType, const QList<RS_Entity*>& list,
485 LC_PropertyContainer* cont) {
486 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
487 QList<LC_PropertyAtomic*>* props) -> void {
488 auto property = createVectorProperty(n, props, container, m_actionContext, m_widget);
489 createDelegatedStorage([this, funGet](EntityClass* e) -> RS_Vector {
490 const RS_Vector wcsVector = funGet(e);
491 const RS_Vector ucsVector = toUCS(wcsVector); // here we return in UCS for editing
492 return ucsVector;
493 }, (funSet != nullptr)
494 ? [this, funSet](const RS_Vector& userUCS, EntityClass* e) -> void {
495 RS_Vector ucsVector = toWCS(userUCS);
496 funSet(ucsVector, e);
497 }
498 : funSet, [this, funGet](RS_Vector& userUCS, EntityClass* e) -> bool {
499 auto originalWCS = funGet(e);
500 auto originalUCS = toUCS(originalWCS);
501 return userUCS == originalUCS;
502 }, entity, property);
503 if (funSet == nullptr) {
504 property->setReadOnly();
505 }
506 }, list, cont);
507}
508
509template <typename EntityClass>
510void LC_EntityTypePropertiesProvider::addEnum(const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
511 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet
512 funGetValue,
513 typename LC_EntityPropertyValueDelegate<
514 LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
515 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
516 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)>
517 funPrepareDescriptor) {
518 add<EntityClass>(names, [this, funGetValue, funSetValue, funPrepareDescriptor, enumDescriptor](
519 const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
520 QList<LC_PropertyAtomic*>* props) -> void {
521 auto property = new LC_PropertyEnum(container, false);
522 property->setNames(n);
523 property->setEnumInfo(enumDescriptor);
524 props->push_back(property);
525 auto valueStorage = new LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>();
526 property->setValueStorage(valueStorage, true);
527 valueStorage->setup(entity, this->m_widget, funGetValue, funSetValue,
528 [funGetValue](LC_PropertyEnumValueType& v, EntityClass* e) -> bool {
529 return v == funGetValue(e);
530 });
531
532 bool readonly = false;
533 if (funPrepareDescriptor != nullptr) {
534 LC_PropertyViewDescriptor descriptor;
535 readonly = funPrepareDescriptor(entity, descriptor);
536 property->setViewDescriptor(descriptor);
537 }
538 if (readonly || funSetValue == nullptr) {
539 property->setReadOnly();
540 }
541 }, list, cont);
542}
543
544template <typename EntityClass>
545void LC_EntityTypePropertiesProvider::addVarEnum(const LC_Property::Names& names,
546 std::function<LC_EnumDescriptor*(EntityClass*)> funEnumDescriptorProvider,
547 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet
548 funGetValue,
549 typename LC_EntityPropertyValueDelegate<
550 LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
551 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
552 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funPrepareDescriptor) {
553 add<EntityClass>(names, [this, funGetValue, funSetValue, funEnumDescriptorProvider, funPrepareDescriptor](
554 const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
555 QList<LC_PropertyAtomic*>* props) -> void {
556 auto property = new LC_PropertyEnum(container, false);
557 property->setNames(n);
558 auto enumInfo = funEnumDescriptorProvider(entity);
559 property->setEnumInfo(enumInfo);
560 props->push_back(property);
561
562 auto valueStorage = new LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>();
563 property->setValueStorage(valueStorage, true);
564 valueStorage->setup(entity, this->m_widget, funGetValue, funSetValue,
565 [funGetValue](LC_PropertyEnumValueType& v, EntityClass* e) -> bool {
566 return v == funGetValue(e);
567 });
568
569 bool readonly = false;
570 if (funPrepareDescriptor != nullptr) {
571 LC_PropertyViewDescriptor descriptor;
572 readonly = funPrepareDescriptor(entity, descriptor);
573 property->setViewDescriptor(descriptor);
574 }
575 if (readonly || funSetValue == nullptr) {
576 property->setReadOnly();
577 }
578 }, list, cont);
579}
580
581template <typename EntityClass>
582void LC_EntityTypePropertiesProvider::addIntSpinbox(const LC_Property::Names& names,
583 typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueGet funGet,
584 typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueSetShort funSet,
585 const QList<RS_Entity*>& list, LC_PropertyContainer* cont, int minVal, int maxVal) {
586 add<EntityClass>(names, [this, funGet, funSet,minVal, maxVal](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
587 QList<LC_PropertyAtomic*>* props) -> void {
588 auto* property = new LC_PropertyInt(container, false);
589 property->setNames(n);
590 props->push_back(property);
591
592 LC_PropertyViewDescriptor descriptor(LC_PropertyIntSpinBoxView::VIEW_NAME);
593 descriptor.attributes[LC_PropertyIntSpinBoxView::ATTR_MIN] = 1;
594 descriptor.attributes[LC_PropertyIntSpinBoxView::ATTR_STEP] = minVal;
595 if (maxVal > 0) {
596 descriptor.attributes[LC_PropertyIntSpinBoxView::ATTR_MAX] = maxVal;
597 }
598 property->setViewDescriptor(descriptor);
599
600 auto valueStorage = new LC_EntityPropertyValueDelegate<int, EntityClass>();
601 valueStorage->setup(entity, m_widget, funGet, funSet, [funGet](int& v, EntityClass* e) -> bool {
602 return v == funGet(e);
603 });
604 property->setValueStorage(valueStorage, true);
605 }, list, cont);
606}
607
608template <typename ValueType, typename EntityClass>
609void LC_EntityTypePropertiesProvider::createDelegatedStorage(
610 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueGet funGet,
611 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueSetShort funSet,
612 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueEqual funEqual, EntityClass* entity,
613 LC_PropertySingle<ValueType>* property) {
614 auto valueStorage = new LC_EntityPropertyValueDelegate<ValueType, EntityClass>();
615 valueStorage->setup(entity, this->m_widget, funGet, funSet, funEqual);
616 property->setValueStorage(valueStorage, true);
617}
618
619template <typename EntityClass>
620void LC_EntityTypePropertiesProvider::createEntityContextCommand(LC_PropertyContainer* container, const QString& propertyName, RS2::ActionType actionType, const QString& linkTitle,
621 const QString& linkTooltip, RS2::ActionType actionTypeRight, const QString& linkTitleRight,
622 const QString& linkTooltipRight, EntityClass* entity,
623 const QString &commonDescription, bool setContextEntity) {
624 auto clickHandler = [this, actionType, actionTypeRight, setContextEntity]([[maybe_unused]] EntityClass* ent, const int linkIndex) {
625 switch (linkIndex) {
626 case 0: {
627 if (setContextEntity) {
628 m_actionContext->saveContextMenuActionContext(ent, ent->getMiddlePoint(), false);
629 }
630 m_actionContext->setCurrentAction(actionType, nullptr);
631 break;
632 }
633 case 1: {
634 if (setContextEntity) {
635 m_actionContext->saveContextMenuActionContext(ent, ent->getMiddlePoint(), false);
636 }
637 m_actionContext->setCurrentAction(actionTypeRight, nullptr);
638 break;
639 }
640 default:
641 break;
642 }
643 };
644 LC_PropertyProviderUtils::createSingleEntityCommand<EntityClass>(container, propertyName, linkTitle,
3
Calling 'createSingleEntityCommand<RS_Line>'
645 linkTooltip, linkTitleRight,
646 linkTooltipRight, entity,
647 clickHandler, commonDescription);
648}
649
650template <typename EntityClass>
651void LC_EntityTypePropertiesProvider::createEntityContextCommands(const std::list<CommandLinkInfo>& links, LC_PropertyContainer* container, EntityClass* entity, const QString &namePrefix,
652 bool setContextEntity) {
653 int idx = 0;
654 for (const auto &i: links) {
655 QString propertyName = QString("%1_%2").arg(namePrefix).arg(idx);
656 createEntityContextCommand(container, propertyName, i.leftLink.actionType, i.leftLink.title, i.leftLink.tooltip,
2
Calling 'LC_EntityTypePropertiesProvider::createEntityContextCommand'
657 i.rightLink.actionType, i.rightLink.title, i.rightLink.tooltip, entity, i.description, setContextEntity);
658 idx++;
659 }
660}
661
662#endif

←

ui/dock_widgets/property_sheet/metaentity/entities/lc_propertyprovider_utils.h

→
1/*
2 * ********************************************************************************
3 * This file is part of the LibreCAD project, a 2D CAD program
4 *
5 * Copyright (C) 2026 LibreCAD.org
6 * Copyright (C) 2026 sand1024
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * ********************************************************************************
22 */
23
24#ifndef LC_PROPERTYPROVIDERUTILS_H
25#define LC_PROPERTYPROVIDERUTILS_H
26
27#include <QTimer>
28
29#include "lc_enum_descriptor.h"
30#include "lc_property_action.h"
31#include "lc_property_action_link_view.h"
32#include "lc_property_bool.h"
33#include "lc_property_container.h"
34#include "lc_property_double.h"
35#include "lc_property_double_interactivepick_view.h"
36#include "lc_property_enum.h"
37#include "lc_property_qstring.h"
38#include "lc_property_single.h"
39#include "lc_property_valuestorage.h"
40#include "rs.h"
41
42namespace LC_PropertyProviderUtils {
43 LC_EnumDescriptor* getLinearUnitsEnumDescriptor(RS2::LinearFormat format);
44 LC_EnumDescriptor* getAngleUnitsEnumDescriptor(RS2::AngleFormat format);
45 LC_EnumDescriptor* getAngleUnitFormatEnumDescriptor();
46 LC_EnumDescriptor* getLinearUnitFormatEnumDescriptor();
47 void notifyDrawingOptionsChanged();
48
49 template <typename ValueType, typename EntityClass>
50 class LC_EntityPropertyValueDirectEntityDelegate : public LC_PropertyValueStorage<ValueType> {
51 public:
52 using PropertyType = LC_PropertyAtomic;
53 using ValueTypeStore = typename LC_PropertyValueStorage<ValueType>::ValueTypeStore;
54
55 using FunValueGet = typename std::function<ValueTypeStore(EntityClass*)>;
56 using FunValueSet = typename std::function<void(ValueType&, LC_PropertyChangeReason, EntityClass*)>;
57
58 ValueType doGetValue() const override {
59 Q_ASSERT(m_funGetValue)static_cast<void>(false && (m_funGetValue));
60 EntityClass* entity = m_entity;
61 auto result = m_funGetValue(entity);
62 return result;
63 }
64
65 void doSetValue(ValueType newValue, LC_PropertyChangeReason reason) override {
66 Q_ASSERT(m_funSetValue)static_cast<void>(false && (m_funSetValue));
67 m_funSetValue(newValue, reason, m_entity);
68 // fixme - do we need some modification there?
69 // m_modificationContext->entityModified(entity, m_entity);
70 }
71
72 bool doCheckValueEqualToCurrent(ValueType valueToCompare) override {
73 return LC_PropertyValueStorage<ValueType>::doCheckValueEqualToCurrent(valueToCompare);
74 }
75
76 void setup(EntityClass* entity, const FunValueGet& funGetValue, const FunValueSet& funSetValue) {
77 m_entity = entity;
78 m_funGetValue = funGetValue;
79 m_funSetValue = funSetValue;
80 }
81
82 protected:
83 EntityClass* m_entity{nullptr};
84
85 FunValueGet m_funGetValue;
86 FunValueSet m_funSetValue;
87 };
88
89 template <typename ValueType, typename EntityClass>
90 void createDirectDelegatedStorage(const typename LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>::FunValueGet &funGet,
91 const std::function<void(const ValueType&, EntityClass*)> &funSet,
92 EntityClass* entity, LC_PropertySingle<ValueType>* property) {
93 auto valueStorage = new LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>();
94
95 auto funSetWrapped = [funSet](const ValueType& v, [[maybe_unused]] LC_PropertyChangeReason reason, EntityClass* e) -> void {
96 funSet(v, e);
97 };
98 valueStorage->setup(entity, funGet, funSetWrapped);
99 property->setValueStorage(valueStorage, true);
100 }
101
102 /// @return the property, which the container owns, for a caller that has more to say about it
103 template <typename EntityClass>
104 LC_PropertyBool* createDirectDelegatedBool(LC_PropertyContainer* container, const LC_Property::Names& names,
105 const typename LC_EntityPropertyValueDirectEntityDelegate<bool, EntityClass>::FunValueGet &funGet,
106 const std::function<void(const bool&, EntityClass*)> &funSet, EntityClass* entity) {
107 auto* property = new LC_PropertyBool(container, false);
108 property->setNames(names);
109 createDirectDelegatedStorage<bool, EntityClass>(funGet, funSet, entity, property);
110 property->setReadOnly(funSet == nullptr);
111 container->addChildProperty(property);
112 return property;
113 }
114
115 template <typename EntityClass>
116 void createDirectDelegatedDouble(LC_PropertyContainer* container, const LC_Property::Names& names,
117 const typename LC_EntityPropertyValueDirectEntityDelegate<double, EntityClass>::FunValueGet &funGet,
118 const std::function<void(const double&, EntityClass*)> &funSet, EntityClass* entity,
119 LC_ActionContext::InteractiveInputInfo::InputType inputType,
120 LC_ActionContext* actionContext, LC_LateCompletionRequestor* requestor) {
121 auto* property = new LC_PropertyDouble(container, false);
122 property->setNames(names);
123 property->setInteractiveInputType(inputType);
124 LC_PropertyViewDescriptor attrs;
125 attrs.viewName = LC_PropertyDoubleInteractivePickView::VIEW_NAME;
126 property->setViewDescriptor(attrs);
127 property->setActionContextAndLaterRequestor(actionContext, requestor);
128 createDirectDelegatedStorage<double, RS_Graphic>(funGet, funSet, entity, property);
129 property->setReadOnly(funSet == nullptr);
130 container->addChildProperty(property);
131 }
132
133 inline void createDirectDelegatedReadonlyString(LC_PropertyContainer* container, const LC_Property::Names& names, const QString& value) {
134 const auto gridTypeProperty = new LC_PropertyQString(container, true);
135 gridTypeProperty->setNames(names);
136 gridTypeProperty->setValue(value);
137 gridTypeProperty->setReadOnly(true);
138 container->addChildProperty(gridTypeProperty);
139 }
140
141 template <typename ValueType, typename EntityClass>
142 auto addDirectEnumWithDescriptor(LC_PropertyContainer* container, const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
143 const typename LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>::FunValueGet &funGetValue,
144 const typename LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>::FunValueSet &funSetValue,
145 EntityClass* entity, std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> &funPrepareDescriptor,
146 bool ownDescriptor = false) -> void {
147 auto property = new LC_PropertyEnum(container, false);
148 property->setNames(names);
149 property->setEnumInfo(enumDescriptor, ownDescriptor);
150 auto valueStorage = new LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>();
151 valueStorage->setup(entity, funGetValue, funSetValue);
152 property->setValueStorage(valueStorage, true);
153
154 bool readonly = false;
155 if (funPrepareDescriptor != nullptr) {
156 LC_PropertyViewDescriptor descriptor;
157 readonly = funPrepareDescriptor(entity, descriptor);
158 property->setViewDescriptor(descriptor);
159 }
160 if (readonly || funSetValue == nullptr) {
161 property->setReadOnly();
162 }
163 container->addChildProperty(property);
164 }
165
166 template <typename ValueType, typename EntityClass>
167 auto addDirectEnum(LC_PropertyContainer* container, const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
168 const typename LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>::FunValueGet &funGet,
169 const std::function<void(const ValueType&, EntityClass*)> &funSet,
170 EntityClass* entity, const bool ownDescriptor = false) -> void {
171 auto property = new LC_PropertyEnum(container, false);
172 property->setNames(names);
173 property->setEnumInfo(enumDescriptor, ownDescriptor);
174 auto valueStorage = new LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>();
175 auto funSetWrapped = [funSet](const ValueType& v, [[maybe_unused]] LC_PropertyChangeReason reason, EntityClass* e) -> void {
176 funSet(v, e);
177 };
178 valueStorage->setup(entity, funGet, funSetWrapped);
179 property->setValueStorage(valueStorage, true);
180 if (funSet == nullptr) {
181 property->setReadOnly();
182 }
183 container->addChildProperty(property);
184 }
185
186 template <typename EntityClass>
187 void createSingleEntityCommand(LC_PropertyContainer* container, const QString& propertyName, const QString& linkTitle,
188 const QString& linkTooltip, const QString& linkTitleRight,
189 const QString& linkTooltipRight, EntityClass* entity,
190 const std::function<void(EntityClass*, int linkIndex)> &clickHandler, const QString &commonDescription) {
191 auto* property = new LC_PropertyAction(container, true);
192 property->setName(propertyName);
193 property->setDisplayName("");
194 LC_PropertyViewDescriptor viewDescriptor("Link");
195 viewDescriptor[LC_PropertyActionLinkView::ATTR_TITLE] = linkTitle;
196 viewDescriptor[LC_PropertyActionLinkView::ATTR_TOOLTIP_LEFT] = linkTooltip;
197 if (!linkTitleRight.isEmpty()) {
4
Assuming the condition is false
5
Taking false branch
198 viewDescriptor[LC_PropertyActionLinkView::ATTR_TITLE_RIGHT] = linkTitleRight;
199 viewDescriptor[LC_PropertyActionLinkView::ATTR_TOOLTIP_RIGHT] = linkTooltipRight;
200 }
201 property->setEntity(entity);
202 auto wrappingClickHandler = [entity, clickHandler](const LC_PropertyAction*, int linkIndex) {
6
Calling copy constructor for 'function<void (RS_Line *, int)>'
20
Returning from copy constructor for 'function<void (RS_Line *, int)>'
21
Potential memory leak
203 QTimer::singleShot(10, [entity, linkIndex, clickHandler] { clickHandler(entity, linkIndex); });
204 };
205 property->setClickHandler(wrappingClickHandler);
206 property->setDescription(commonDescription);
207 property->setViewDescriptor(viewDescriptor);
208 container->addChildProperty(property);
209 }
210}
211
212#endif

←

lib/properties/lc_property_view_descriptor.h

→
1/*
2 * ********************************************************************************
3 * This file is part of the LibreCAD project, a 2D CAD program
4 *
5 * Copyright (C) 2025 LibreCAD.org
6 * Copyright (C) 2025 sand1024
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * ********************************************************************************
22 */
23
24#ifndef LC_PROPERTYVIEWDESCRIPTOR_H
25#define LC_PROPERTYVIEWDESCRIPTOR_H
26
27#include <QVariant>
28
29struct LC_PropertyViewDescriptor {
30 QByteArray viewName;
31 using Attributes = QMap<QByteArray, QVariant>;
32 Attributes attributes;
33
34 LC_PropertyViewDescriptor() = default;
35 LC_PropertyViewDescriptor(const LC_PropertyViewDescriptor& other);
36 LC_PropertyViewDescriptor& operator=(const LC_PropertyViewDescriptor&) = default;
37 explicit LC_PropertyViewDescriptor(const QByteArray& name, const Attributes& attributes = Attributes());
38 LC_PropertyViewDescriptor(const Attributes& attributes);
39
40 QVariant& operator[](const QByteArray& idx) {
41 return attributes[idx];
42 }
43
44 QVariant operator[](const QByteArray& idx) const {
45 return attributes[idx];
46 }
47
48 template <typename T>
49 T attr(const QByteArray& attrName, const T& defaultValue = T()) const {
50 const auto it = attributes.find(attrName);
51 if (it == attributes.end()) {
52 return defaultValue;
53 }
54 return it.value().value<T>();
55 }
56
57 template <typename T>
58 bool load(const QByteArray& attrName, T& destination) const {
59 const auto it = attributes.find(attrName);
60 if (it == attributes.end()) {
61 return false;
62 }
63 destination = it.value().value<T>();
64 return true;
65 }
66
67 template <typename OBJ_T, typename ATTR_T_RET, typename ATTR_T_ARG>
68 void store(const QByteArray& attrName, OBJ_T* to, ATTR_T_RET (OBJ_T::*get)() const, void (OBJ_T::*set)(ATTR_T_ARG)) const {
69 Q_ASSERT(to)static_cast<void>(false && (to));
70 (to->*set)(attr(attrName, (to->*get)()));
71 }
72};
73
74#endif

←

/usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/bits/std_function.h

1// Implementation of std::function -*- C++ -*-
2
3// Copyright (C) 2004-2025 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// <http://www.gnu.org/licenses/>.
24
25/** @file include/bits/std_function.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{functional}
28 */
29
30#ifndef _GLIBCXX_STD_FUNCTION_H1
31#define _GLIBCXX_STD_FUNCTION_H1 1
32
33#ifdef _GLIBCXX_SYSHDR
34#pragma GCC system_header
35#endif
36
37#if __cplusplus201703L < 201103L
38# include <bits/c++0x_warning.h>
39#else
40
41#include <new> // placement new
42#include <typeinfo> // typeid
43#include <bits/invoke.h> // __invoke_r
44#include <bits/refwrap.h> // ref wrapper, _Maybe_unary_or_binary_function
45#include <bits/functexcept.h> // __throw_bad_function_call
46
47namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
48{
49_GLIBCXX_BEGIN_NAMESPACE_VERSION
50
51 /**
52 * @brief Exception class thrown when class template function's
53 * operator() is called with an empty target.
54 * @ingroup exceptions
55 */
56 class bad_function_call : public std::exception
57 {
58 public:
59 virtual ~bad_function_call() noexcept;
60
61 const char* what() const noexcept;
62 };
63
64 /**
65 * Trait identifying "location-invariant" types, meaning that the
66 * address of the object (or any of its members) will not escape.
67 * Trivially copyable types are location-invariant and users can
68 * specialize this trait for other types.
69 */
70 template<typename _Tp>
71 struct __is_location_invariant
72 : is_trivially_copyable<_Tp>::type
73 { };
74
75 class _Undefined_class;
76
77 union _Nocopy_types
78 {
79 void* _M_object;
80 const void* _M_const_object;
81 void (*_M_function_pointer)();
82 void (_Undefined_class::*_M_member_pointer)();
83 };
84
85 union [[gnu::may_alias]] _Any_data
86 {
87 void* _M_access() noexcept { return &_M_pod_data[0]; }
88 const void* _M_access() const noexcept { return &_M_pod_data[0]; }
89
90 template<typename _Tp>
91 _Tp&
92 _M_access() noexcept
93 { return *static_cast<_Tp*>(_M_access()); }
94
95 template<typename _Tp>
96 const _Tp&
97 _M_access() const noexcept
98 { return *static_cast<const _Tp*>(_M_access()); }
99
100 _Nocopy_types _M_unused;
101 char _M_pod_data[sizeof(_Nocopy_types)];
102 };
103
104 enum _Manager_operation
105 {
106 __get_type_info,
107 __get_functor_ptr,
108 __clone_functor,
109 __destroy_functor
110 };
111
112 template<typename _Signature>
113 class function;
114
115 /// Base class of all polymorphic function object wrappers.
116 class _Function_base
117 {
118 public:
119 static const size_t _M_max_size = sizeof(_Nocopy_types);
120 static const size_t _M_max_align = __alignof__(_Nocopy_types);
121
122 template<typename _Functor>
123 class _Base_manager
124 {
125 protected:
126 static const bool __stored_locally =
127 (__is_location_invariant<_Functor>::value
128 && sizeof(_Functor) <= _M_max_size
129 && __alignof__(_Functor) <= _M_max_align
130 && (_M_max_align % __alignof__(_Functor) == 0));
131
132 using _Local_storage = integral_constant<bool, __stored_locally>;
133
134 // Retrieve a pointer to the function object
135 static _Functor*
136 _M_get_pointer(const _Any_data& __source) noexcept
137 {
138 if _GLIBCXX17_CONSTEXPRconstexpr (__stored_locally)
139 {
140 const _Functor& __f = __source._M_access<_Functor>();
141 return const_cast<_Functor*>(std::__addressof(__f));
142 }
143 else // have stored a pointer
144 return __source._M_access<_Functor*>();
145 }
146
147 private:
148 // Construct a location-invariant function object that fits within
149 // an _Any_data structure.
150 template<typename _Fn>
151 static void
152 _M_create(_Any_data& __dest, _Fn&& __f, true_type)
153 {
154 ::new (__dest._M_access()) _Functor(std::forward<_Fn>(__f));
155 }
156
157 // Construct a function object on the heap and store a pointer.
158 template<typename _Fn>
159 static void
160 _M_create(_Any_data& __dest, _Fn&& __f, false_type)
161 {
162 __dest._M_access<_Functor*>()
163 = new _Functor(std::forward<_Fn>(__f));
14
Memory is allocated
164 }
165
166 // Destroy an object stored in the internal buffer.
167 static void
168 _M_destroy(_Any_data& __victim, true_type)
169 {
170 __victim._M_access<_Functor>().~_Functor();
171 }
172
173 // Destroy an object located on the heap.
174 static void
175 _M_destroy(_Any_data& __victim, false_type)
176 {
177 delete __victim._M_access<_Functor*>();
178 }
179
180 public:
181 static bool
182 _M_manager(_Any_data& __dest, const _Any_data& __source,
183 _Manager_operation __op)
184 {
185 switch (__op)
11
Control jumps to 'case __clone_functor:' at line 199
186 {
187 case __get_type_info:
188#if __cpp_rtti199711L
189 __dest._M_access<const type_info*>() = &typeid(_Functor);
190#else
191 __dest._M_access<const type_info*>() = nullptr;
192#endif
193 break;
194
195 case __get_functor_ptr:
196 __dest._M_access<_Functor*>() = _M_get_pointer(__source);
197 break;
198
199 case __clone_functor:
200 _M_init_functor(__dest,
12
Calling '_Base_manager::_M_init_functor'
16
Returned allocated memory
201 *const_cast<const _Functor*>(_M_get_pointer(__source)));
202 break;
17
Execution continues on line 208
203
204 case __destroy_functor:
205 _M_destroy(__dest, _Local_storage());
206 break;
207 }
208 return false;
209 }
210
211 template<typename _Fn>
212 static void
213 _M_init_functor(_Any_data& __functor, _Fn&& __f)
214 noexcept(__and_<_Local_storage,
215 is_nothrow_constructible<_Functor, _Fn>>::value)
216 {
217 _M_create(__functor, std::forward<_Fn>(__f), _Local_storage());
13
Calling '_Base_manager::_M_create'
15
Returned allocated memory
218 }
219
220 template<typename _Signature>
221 static bool
222 _M_not_empty_function(const function<_Signature>& __f) noexcept
223 { return static_cast<bool>(__f); }
224
225 template<typename _Tp>
226 static bool
227 _M_not_empty_function(_Tp* __fp) noexcept
228 { return __fp != nullptr; }
229
230 template<typename _Class, typename _Tp>
231 static bool
232 _M_not_empty_function(_Tp _Class::* __mp) noexcept
233 { return __mp != nullptr; }
234
235 template<typename _Tp>
236 static bool
237 _M_not_empty_function(const _Tp&) noexcept
238 { return true; }
239 };
240
241 _Function_base() = default;
242
243 ~_Function_base()
244 {
245 if (_M_manager)
246 _M_manager(_M_functor, _M_functor, __destroy_functor);
247 }
248
249 bool _M_empty() const { return !_M_manager; }
250
251 using _Manager_type
252 = bool (*)(_Any_data&, const _Any_data&, _Manager_operation);
253
254 _Any_data _M_functor{};
255 _Manager_type _M_manager{};
256 };
257
258 template<typename _Signature, typename _Functor>
259 class _Function_handler;
260
261 template<typename _Res, typename _Functor, typename... _ArgTypes>
262 class _Function_handler<_Res(_ArgTypes...), _Functor>
263 : public _Function_base::_Base_manager<_Functor>
264 {
265 using _Base = _Function_base::_Base_manager<_Functor>;
266
267 public:
268 static bool
269 _M_manager(_Any_data& __dest, const _Any_data& __source,
270 _Manager_operation __op)
271 {
272 switch (__op)
9
Control jumps to the 'default' case at line 283
273 {
274#if __cpp_rtti199711L
275 case __get_type_info:
276 __dest._M_access<const type_info*>() = &typeid(_Functor);
277 break;
278#endif
279 case __get_functor_ptr:
280 __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source);
281 break;
282
283 default:
284 _Base::_M_manager(__dest, __source, __op);
10
Calling '_Base_manager::_M_manager'
18
Returned allocated memory
285 }
286 return false;
287 }
288
289 static _Res
290 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
291 {
292 return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor),
293 std::forward<_ArgTypes>(__args)...);
294 }
295
296 template<typename _Fn>
297 static constexpr bool
298 _S_nothrow_init() noexcept
299 {
300 return __and_<typename _Base::_Local_storage,
301 is_nothrow_constructible<_Functor, _Fn>>::value;
302 }
303 };
304
305 // Specialization for invalid types
306 template<>
307 class _Function_handler<void, void>
308 {
309 public:
310 static bool
311 _M_manager(_Any_data&, const _Any_data&, _Manager_operation)
312 { return false; }
313 };
314
315 // Avoids instantiating ill-formed specializations of _Function_handler
316 // in std::function<_Signature>::target<_Functor>().
317 // e.g. _Function_handler<Sig, void()> and _Function_handler<Sig, void>
318 // would be ill-formed.
319 template<typename _Signature, typename _Functor,
320 bool __valid = is_object<_Functor>::value>
321 struct _Target_handler
322 : _Function_handler<_Signature, typename remove_cv<_Functor>::type>
323 { };
324
325 template<typename _Signature, typename _Functor>
326 struct _Target_handler<_Signature, _Functor, false>
327 : _Function_handler<void, void>
328 { };
329
330 /**
331 * @brief Polymorphic function wrapper.
332 * @ingroup functors
333 * @since C++11
334 */
335 template<typename _Res, typename... _ArgTypes>
336 class function<_Res(_ArgTypes...)>
337 : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
338 private _Function_base
339 {
340 // Equivalent to std::decay_t except that it produces an invalid type
341 // if the decayed type is the current specialization of std::function.
342 template<typename _Func,
343 bool _Self = is_same<__remove_cvref_t<_Func>, function>::value>
344 using _Decay_t
345 = typename __enable_if_t<!_Self, decay<_Func>>::type;
346
347 template<typename _Func,
348 typename _DFunc = _Decay_t<_Func>,
349 typename _Res2 = __invoke_result<_DFunc&, _ArgTypes...>>
350 struct _Callable
351 : __is_invocable_impl<_Res2, _Res>::type
352 { };
353
354 template<typename _Cond, typename _Tp = void>
355 using _Requires = __enable_if_t<_Cond::value, _Tp>;
356
357 template<typename _Functor>
358 using _Handler
359 = _Function_handler<_Res(_ArgTypes...), __decay_t<_Functor>>;
360
361 public:
362 typedef _Res result_type;
363
364 // [3.7.2.1] construct/copy/destroy
365
366 /**
367 * @brief Default construct creates an empty function call wrapper.
368 * @post `!(bool)*this`
369 */
370 function() noexcept
371 : _Function_base() { }
372
373 /**
374 * @brief Creates an empty function call wrapper.
375 * @post @c !(bool)*this
376 */
377 function(nullptr_t) noexcept
378 : _Function_base() { }
379
380 /**
381 * @brief %Function copy constructor.
382 * @param __x A %function object with identical call signature.
383 * @post `bool(*this) == bool(__x)`
384 *
385 * The newly-created %function contains a copy of the target of
386 * `__x` (if it has one).
387 */
388 function(const function& __x)
389 : _Function_base()
390 {
391 if (static_cast<bool>(__x))
7
Taking true branch
392 {
393 __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
8
Calling '_Function_handler::_M_manager'
19
Returned allocated memory
394 _M_invoker = __x._M_invoker;
395 _M_manager = __x._M_manager;
396 }
397 }
398
399 /**
400 * @brief %Function move constructor.
401 * @param __x A %function object rvalue with identical call signature.
402 *
403 * The newly-created %function contains the target of `__x`
404 * (if it has one).
405 */
406 function(function&& __x) noexcept
407 : _Function_base(), _M_invoker(__x._M_invoker)
408 {
409 if (static_cast<bool>(__x))
410 {
411 _M_functor = __x._M_functor;
412 _M_manager = __x._M_manager;
413 __x._M_manager = nullptr;
414 __x._M_invoker = nullptr;
415 }
416 }
417
418 /**
419 * @brief Builds a %function that targets a copy of the incoming
420 * function object.
421 * @param __f A %function object that is callable with parameters of
422 * type `ArgTypes...` and returns a value convertible to `Res`.
423 *
424 * The newly-created %function object will target a copy of
425 * `__f`. If `__f` is `reference_wrapper<F>`, then this function
426 * object will contain a reference to the function object `__f.get()`.
427 * If `__f` is a null function pointer, null pointer-to-member, or
428 * empty `std::function`, the newly-created object will be empty.
429 *
430 * If `__f` is a non-null function pointer or an object of type
431 * `reference_wrapper<F>`, this function will not throw.
432 */
433 // _GLIBCXX_RESOLVE_LIB_DEFECTS
434 // 2774. std::function construction vs assignment
435 template<typename _Functor,
436 typename _Constraints = _Requires<_Callable<_Functor>>>
437 function(_Functor&& __f)
438 noexcept(_Handler<_Functor>::template _S_nothrow_init<_Functor>())
439 : _Function_base()
440 {
441 static_assert(is_copy_constructible<__decay_t<_Functor>>::value,
442 "std::function target must be copy-constructible");
443 static_assert(is_constructible<__decay_t<_Functor>, _Functor>::value,
444 "std::function target must be constructible from the "
445 "constructor argument");
446
447 using _My_handler = _Handler<_Functor>;
448
449 if (_My_handler::_M_not_empty_function(__f))
450 {
451 _My_handler::_M_init_functor(_M_functor,
452 std::forward<_Functor>(__f));
453 _M_invoker = &_My_handler::_M_invoke;
454 _M_manager = &_My_handler::_M_manager;
455 }
456 }
457
458 /**
459 * @brief Function assignment operator.
460 * @param __x A %function with identical call signature.
461 * @post `(bool)*this == (bool)x`
462 * @returns `*this`
463 *
464 * The target of `__x` is copied to `*this`. If `__x` has no
465 * target, then `*this` will be empty.
466 *
467 * If `__x` targets a function pointer or a reference to a function
468 * object, then this operation will not throw an exception.
469 */
470 function&
471 operator=(const function& __x)
472 {
473 function(__x).swap(*this);
474 return *this;
475 }
476
477 /**
478 * @brief Function move-assignment operator.
479 * @param __x A %function rvalue with identical call signature.
480 * @returns `*this`
481 *
482 * The target of `__x` is moved to `*this`. If `__x` has no
483 * target, then `*this` will be empty.
484 *
485 * If `__x` targets a function pointer or a reference to a function
486 * object, then this operation will not throw an exception.
487 */
488 function&
489 operator=(function&& __x) noexcept
490 {
491 function(std::move(__x)).swap(*this);
492 return *this;
493 }
494
495 /**
496 * @brief Function assignment to empty.
497 * @post `!(bool)*this`
498 * @returns `*this`
499 *
500 * The target of `*this` is deallocated, leaving it empty.
501 */
502 function&
503 operator=(nullptr_t) noexcept
504 {
505 if (_M_manager)
506 {
507 _M_manager(_M_functor, _M_functor, __destroy_functor);
508 _M_manager = nullptr;
509 _M_invoker = nullptr;
510 }
511 return *this;
512 }
513
514 /**
515 * @brief Function assignment to a new target.
516 * @param __f A function object that is callable with parameters of
517 * type `_ArgTypes...` and returns a value convertible
518 * to `_Res`.
519 * @return `*this`
520 * @since C++11
521 *
522 * This function object wrapper will target a copy of `__f`. If `__f`
523 * is `reference_wrapper<F>`, then this function object will contain
524 * a reference to the function object `__f.get()`. If `__f` is a null
525 * function pointer or null pointer-to-member, this object will be
526 * empty.
527 *
528 * If `__f` is a non-null function pointer or an object of type
529 * `reference_wrapper<F>`, this function will not throw.
530 */
531 template<typename _Functor>
532 _Requires<_Callable<_Functor>, function&>
533 operator=(_Functor&& __f)
534 noexcept(_Handler<_Functor>::template _S_nothrow_init<_Functor>())
535 {
536 function(std::forward<_Functor>(__f)).swap(*this);
537 return *this;
538 }
539
540 /// @overload
541 template<typename _Functor>
542 function&
543 operator=(reference_wrapper<_Functor> __f) noexcept
544 {
545 function(__f).swap(*this);
546 return *this;
547 }
548
549 // [3.7.2.2] function modifiers
550
551 /**
552 * @brief Swap the targets of two %function objects.
553 * @param __x A %function with identical call signature.
554 *
555 * Swap the targets of `this` function object and `__f`.
556 * This function will not throw exceptions.
557 */
558 void swap(function& __x) noexcept
559 {
560 std::swap(_M_functor, __x._M_functor);
561 std::swap(_M_manager, __x._M_manager);
562 std::swap(_M_invoker, __x._M_invoker);
563 }
564
565 // [3.7.2.3] function capacity
566
567 /**
568 * @brief Determine if the %function wrapper has a target.
569 *
570 * @return `true` when this function object contains a target,
571 * or `false` when it is empty.
572 *
573 * This function will not throw exceptions.
574 */
575 explicit operator bool() const noexcept
576 { return !_M_empty(); }
577
578 // [3.7.2.4] function invocation
579
580 /**
581 * @brief Invokes the function targeted by `*this`.
582 * @returns the result of the target.
583 * @throws `bad_function_call` when `!(bool)*this`
584 *
585 * The function call operator invokes the target function object
586 * stored by `this`.
587 */
588 _Res
589 operator()(_ArgTypes... __args) const
590 {
591 if (_M_empty())
592 __throw_bad_function_call();
593 return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
594 }
595
596#if __cpp_rtti199711L
597 // [3.7.2.5] function target access
598 /**
599 * @brief Determine the type of the target of this function object
600 * wrapper.
601 *
602 * @returns the type identifier of the target function object, or
603 * `typeid(void)` if `!(bool)*this`.
604 *
605 * This function will not throw exceptions.
606 */
607 const type_info&
608 target_type() const noexcept
609 {
610 if (_M_manager)
611 {
612 _Any_data __typeinfo_result;
613 _M_manager(__typeinfo_result, _M_functor, __get_type_info);
614 if (auto __ti = __typeinfo_result._M_access<const type_info*>())
615 return *__ti;
616 }
617 return typeid(void);
618 }
619#endif
620
621 /**
622 * @brief Access the stored target function object.
623 *
624 * @return Returns a pointer to the stored target function object,
625 * if `typeid(_Functor).equals(target_type())`; otherwise, a null
626 * pointer.
627 *
628 * This function does not throw exceptions.
629 *
630 * @{
631 */
632 template<typename _Functor>
633 _Functor*
634 target() noexcept
635 {
636 const function* __const_this = this;
637 const _Functor* __func = __const_this->template target<_Functor>();
638 // If is_function_v<_Functor> is true then const_cast<_Functor*>
639 // would be ill-formed, so use *const_cast<_Functor**> instead.
640 return *const_cast<_Functor**>(&__func);
641 }
642
643 template<typename _Functor>
644 const _Functor*
645 target() const noexcept
646 {
647 if _GLIBCXX17_CONSTEXPRconstexpr (is_object<_Functor>::value)
648 {
649 // For C++11 and C++14 if-constexpr is not used above, so
650 // _Target_handler avoids ill-formed _Function_handler types.
651 using _Handler = _Target_handler<_Res(_ArgTypes...), _Functor>;
652
653 if (_M_manager == &_Handler::_M_manager
654#if __cpp_rtti199711L
655 || (_M_manager && typeid(_Functor) == target_type())
656#endif
657 )
658 {
659 _Any_data __ptr;
660 _M_manager(__ptr, _M_functor, __get_functor_ptr);
661 return __ptr._M_access<const _Functor*>();
662 }
663 }
664 return nullptr;
665 }
666 /// @}
667
668 private:
669 using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
670 _Invoker_type _M_invoker = nullptr;
671 };
672
673#if __cpp_deduction_guides201703L >= 201606
674 template<typename>
675 struct __function_guide_helper
676 { };
677
678 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
679 struct __function_guide_helper<
680 _Res (_Tp::*) (_Args...) noexcept(_Nx)
681 >
682 { using type = _Res(_Args...); };
683
684 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
685 struct __function_guide_helper<
686 _Res (_Tp::*) (_Args...) & noexcept(_Nx)
687 >
688 { using type = _Res(_Args...); };
689
690 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
691 struct __function_guide_helper<
692 _Res (_Tp::*) (_Args...) const noexcept(_Nx)
693 >
694 { using type = _Res(_Args...); };
695
696 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
697 struct __function_guide_helper<
698 _Res (_Tp::*) (_Args...) const & noexcept(_Nx)
699 >
700 { using type = _Res(_Args...); };
701
702#if __cpp_explicit_this_parameter >= 202110L
703 // _GLIBCXX_RESOLVE_LIB_DEFECTS
704 // 3617. function/packaged_task deduction guides and deducing this
705 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
706 struct __function_guide_helper<_Res (*) (_Tp, _Args...) noexcept(_Nx)>
707 { using type = _Res(_Args...); };
708#endif
709
710#if __cpp_static_call_operator202207L >= 202207L && __cpp_concepts >= 202002L
711 template<typename _StaticCallOp>
712 struct __function_guide_static_helper
713 { };
714
715 template<typename _Res, bool _Nx, typename... _Args>
716 struct __function_guide_static_helper<_Res (*) (_Args...) noexcept(_Nx)>
717 { using type = _Res(_Args...); };
718
719 template<typename _Fn, typename _Op>
720 using __function_guide_t = typename __conditional_t<
721 requires (_Fn& __f) { (void) __f.operator(); },
722 __function_guide_static_helper<_Op>,
723 __function_guide_helper<_Op>>::type;
724#else
725 template<typename _Fn, typename _Op>
726 using __function_guide_t = typename __function_guide_helper<_Op>::type;
727#endif
728
729 template<typename _Res, typename... _ArgTypes>
730 function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
731
732 template<typename _Fn, typename _Signature
733 = __function_guide_t<_Fn, decltype(&_Fn::operator())>>
734 function(_Fn) -> function<_Signature>;
735#endif
736
737 // [20.7.15.2.6] null pointer comparisons
738
739 /**
740 * @brief Test whether a polymorphic function object wrapper is empty.
741 * @returns `true` if the wrapper has no target, `false` otherwise
742 *
743 * This function will not throw exceptions.
744 */
745 template<typename _Res, typename... _Args>
746 inline bool
747 operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
748 { return !static_cast<bool>(__f); }
749
750#if __cpp_impl_three_way_comparison < 201907L
751 /// @overload
752 template<typename _Res, typename... _Args>
753 inline bool
754 operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
755 { return !static_cast<bool>(__f); }
756
757 /**
758 * @brief Test whether a polymorphic function object wrapper is non-empty.
759 * @returns `false` if the wrapper has no target, `true` otherwise
760 *
761 * This function will not throw exceptions.
762 */
763 template<typename _Res, typename... _Args>
764 inline bool
765 operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
766 { return static_cast<bool>(__f); }
767
768 /// @overload
769 template<typename _Res, typename... _Args>
770 inline bool
771 operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
772 { return static_cast<bool>(__f); }
773#endif
774
775 // [20.7.15.2.7] specialized algorithms
776
777 /**
778 * @brief Swap the targets of two polymorphic function object wrappers.
779 *
780 * This function will not throw exceptions.
781 */
782 // _GLIBCXX_RESOLVE_LIB_DEFECTS
783 // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps
784 template<typename _Res, typename... _Args>
785 inline void
786 swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
787 { __x.swap(__y); }
788
789#if __cplusplus201703L >= 201703L
790 namespace __detail::__variant
791 {
792 template<typename> struct _Never_valueless_alt; // see <variant>
793
794 // Provide the strong exception-safety guarantee when emplacing a
795 // function into a variant.
796 template<typename _Signature>
797 struct _Never_valueless_alt<std::function<_Signature>>
798 : std::true_type
799 { };
800 } // namespace __detail::__variant
801#endif // C++17
802
803_GLIBCXX_END_NAMESPACE_VERSION
804} // namespace std
805
806#endif // C++11
807#endif // _GLIBCXX_STD_FUNCTION_H