Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -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-18/lib/clang/18 -D _REENTRANT -D DWGSUPPORT -D MUPARSER_STATIC -D QC_APPDIR="librecad" -D LC_VERSION=2.2.2_alpha1-607-g330d41cec -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/jwwlib/src -I ../../libraries/shapelib/src -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/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/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -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-08-04-154929-5069-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("Create parallel line through point")},
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 orhtogonal to this line")},
146 {RS2::ActionDrawLineRelAngle, tr("Relative Angle"), tr("Create line with related angle to this line")}
147 },
148 {
149 tr("Creation 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 2 points")},
156 {RS2::ActionDrawCircleTangental2Entities1Point, tr("Tangential Circle (2 E, 1 P)"), tr("Create circle tangental by 2 entitites 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 Cicle (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 elipse inscribed")},
166 {RS2::ActionDrawBoundingBox, tr("Bounding box"), tr("Create of 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 intesection 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/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_list.h

1// List implementation -*- C++ -*-
2
3// Copyright (C) 2001-2024 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#if __cplusplus201703L >= 201103L
63#include <initializer_list>
64#include <bits/allocated_ptr.h>
65#include <ext/aligned_buffer.h>
66#endif
67
68namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
69{
70_GLIBCXX_BEGIN_NAMESPACE_VERSION
71
72 namespace __detail
73 {
74 // Supporting structures are split into common and templated
75 // types; the latter publicly inherits from the former in an
76 // effort to reduce code duplication. This results in some
77 // "needless" static_cast'ing later on, but it's all safe
78 // downcasting.
79
80 /// Common part of a node in the %list.
81 struct _List_node_base
82 {
83 _List_node_base* _M_next;
84 _List_node_base* _M_prev;
85
86 static void
87 swap(_List_node_base& __x, _List_node_base& __y) _GLIBCXX_USE_NOEXCEPTnoexcept;
88
89 void
90 _M_transfer(_List_node_base* const __first,
91 _List_node_base* const __last) _GLIBCXX_USE_NOEXCEPTnoexcept;
92
93 void
94 _M_reverse() _GLIBCXX_USE_NOEXCEPTnoexcept;
95
96 void
97 _M_hook(_List_node_base* const __position) _GLIBCXX_USE_NOEXCEPTnoexcept;
98
99 void
100 _M_unhook() _GLIBCXX_USE_NOEXCEPTnoexcept;
101 };
102
103 /// The %list node header.
104 struct _List_node_header : public _List_node_base
105 {
106#if _GLIBCXX_USE_CXX11_ABI1
107 std::size_t _M_size;
108#endif
109
110 _List_node_header() _GLIBCXX_NOEXCEPTnoexcept
111 { _M_init(); }
112
113#if __cplusplus201703L >= 201103L
114 _List_node_header(_List_node_header&& __x) noexcept
115 : _List_node_base{ __x._M_next, __x._M_prev }
116# if _GLIBCXX_USE_CXX11_ABI1
117 , _M_size(__x._M_size)
118# endif
119 {
120 if (__x._M_base()->_M_next == __x._M_base())
121 this->_M_next = this->_M_prev = this;
122 else
123 {
124 this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base();
125 __x._M_init();
126 }
127 }
128
129 void
130 _M_move_nodes(_List_node_header&& __x)
131 {
132 _List_node_base* const __xnode = __x._M_base();
133 if (__xnode->_M_next == __xnode)
134 _M_init();
135 else
136 {
137 _List_node_base* const __node = this->_M_base();
138 __node->_M_next = __xnode->_M_next;
139 __node->_M_prev = __xnode->_M_prev;
140 __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
141# if _GLIBCXX_USE_CXX11_ABI1
142 _M_size = __x._M_size;
143# endif
144 __x._M_init();
145 }
146 }
147#endif
148
149 void
150 _M_init() _GLIBCXX_NOEXCEPTnoexcept
151 {
152 this->_M_next = this->_M_prev = this;
153#if _GLIBCXX_USE_CXX11_ABI1
154 this->_M_size = 0;
155#endif
156 }
157
158 private:
159 _List_node_base* _M_base() { return this; }
160 };
161
162 // Used by list::sort to hold nodes being sorted.
163 struct _Scratch_list : _List_node_base
164 {
165 _Scratch_list() { _M_next = _M_prev = this; }
166
167 bool empty() const { return _M_next == this; }
168
169 void swap(_List_node_base& __l) { _List_node_base::swap(*this, __l); }
170
171 template<typename _Iter, typename _Cmp>
172 struct _Ptr_cmp
173 {
174 _Cmp _M_cmp;
175
176 bool
177 operator()(__detail::_List_node_base* __lhs,
178 __detail::_List_node_base* __rhs) /* not const */
179 { return _M_cmp(*_Iter(__lhs), *_Iter(__rhs)); }
180 };
181
182 template<typename _Iter>
183 struct _Ptr_cmp<_Iter, void>
184 {
185 bool
186 operator()(__detail::_List_node_base* __lhs,
187 __detail::_List_node_base* __rhs) const
188 { return *_Iter(__lhs) < *_Iter(__rhs); }
189 };
190
191 // Merge nodes from __x into *this. Both lists must be sorted wrt _Cmp.
192 template<typename _Cmp>
193 void
194 merge(_List_node_base& __x, _Cmp __comp)
195 {
196 _List_node_base* __first1 = _M_next;
197 _List_node_base* const __last1 = this;
198 _List_node_base* __first2 = __x._M_next;
199 _List_node_base* const __last2 = std::__addressof(__x);
200
201 while (__first1 != __last1 && __first2 != __last2)
202 {
203 if (__comp(__first2, __first1))
204 {
205 _List_node_base* __next = __first2->_M_next;
206 __first1->_M_transfer(__first2, __next);
207 __first2 = __next;
208 }
209 else
210 __first1 = __first1->_M_next;
211 }
212 if (__first2 != __last2)
213 this->_M_transfer(__first2, __last2);
214 }
215
216 // Splice the node at __i into *this.
217 void _M_take_one(_List_node_base* __i)
218 { this->_M_transfer(__i, __i->_M_next); }
219
220 // Splice all nodes from *this after __i.
221 void _M_put_all(_List_node_base* __i)
222 {
223 if (!empty())
224 __i->_M_transfer(_M_next, this);
225 }
226 };
227
228 } // namespace detail
229
230_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
231
232 /// An actual node in the %list.
233 template<typename _Tp>
234 struct _List_node : public __detail::_List_node_base
235 {
236#if __cplusplus201703L >= 201103L
237 __gnu_cxx::__aligned_membuf<_Tp> _M_storage;
238 _Tp* _M_valptr() { return _M_storage._M_ptr(); }
239 _Tp const* _M_valptr() const { return _M_storage._M_ptr(); }
240#else
241 _Tp _M_data;
242 _Tp* _M_valptr() { return std::__addressof(_M_data); }
243 _Tp const* _M_valptr() const { return std::__addressof(_M_data); }
244#endif
245 };
246
247 /**
248 * @brief A list::iterator.
249 *
250 * All the functions are op overloads.
251 */
252 template<typename _Tp>
253 struct _List_iterator
254 {
255 typedef _List_iterator<_Tp> _Self;
256 typedef _List_node<_Tp> _Node;
257
258 typedef ptrdiff_t difference_type;
259 typedef std::bidirectional_iterator_tag iterator_category;
260 typedef _Tp value_type;
261 typedef _Tp* pointer;
262 typedef _Tp& reference;
263
264 _List_iterator() _GLIBCXX_NOEXCEPTnoexcept
265 : _M_node() { }
266
267 explicit
268 _List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPTnoexcept
269 : _M_node(__x) { }
270
271 _Self
272 _M_const_cast() const _GLIBCXX_NOEXCEPTnoexcept
273 { return *this; }
274
275 // Must downcast from _List_node_base to _List_node to get to value.
276 _GLIBCXX_NODISCARD[[__nodiscard__]]
277 reference
278 operator*() const _GLIBCXX_NOEXCEPTnoexcept
279 { return *static_cast<_Node*>(_M_node)->_M_valptr(); }
280
281 _GLIBCXX_NODISCARD[[__nodiscard__]]
282 pointer
283 operator->() const _GLIBCXX_NOEXCEPTnoexcept
284 { return static_cast<_Node*>(_M_node)->_M_valptr(); }
285
286 _Self&
287 operator++() _GLIBCXX_NOEXCEPTnoexcept
288 {
289 _M_node = _M_node->_M_next;
290 return *this;
291 }
292
293 _Self
294 operator++(int) _GLIBCXX_NOEXCEPTnoexcept
295 {
296 _Self __tmp = *this;
297 _M_node = _M_node->_M_next;
298 return __tmp;
299 }
300
301 _Self&
302 operator--() _GLIBCXX_NOEXCEPTnoexcept
303 {
304 _M_node = _M_node->_M_prev;
305 return *this;
306 }
307
308 _Self
309 operator--(int) _GLIBCXX_NOEXCEPTnoexcept
310 {
311 _Self __tmp = *this;
312 _M_node = _M_node->_M_prev;
313 return __tmp;
314 }
315
316 _GLIBCXX_NODISCARD[[__nodiscard__]]
317 friend bool
318 operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPTnoexcept
319 { return __x._M_node == __y._M_node; }
320
321#if __cpp_impl_three_way_comparison < 201907L
322 _GLIBCXX_NODISCARD[[__nodiscard__]]
323 friend bool
324 operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPTnoexcept
325 { return __x._M_node != __y._M_node; }
326#endif
327
328 // The only member points to the %list element.
329 __detail::_List_node_base* _M_node;
330 };
331
332 /**
333 * @brief A list::const_iterator.
334 *
335 * All the functions are op overloads.
336 */
337 template<typename _Tp>
338 struct _List_const_iterator
339 {
340 typedef _List_const_iterator<_Tp> _Self;
341 typedef const _List_node<_Tp> _Node;
342 typedef _List_iterator<_Tp> iterator;
343
344 typedef ptrdiff_t difference_type;
345 typedef std::bidirectional_iterator_tag iterator_category;
346 typedef _Tp value_type;
347 typedef const _Tp* pointer;
348 typedef const _Tp& reference;
349
350 _List_const_iterator() _GLIBCXX_NOEXCEPTnoexcept
351 : _M_node() { }
352
353 explicit
354 _List_const_iterator(const __detail::_List_node_base* __x)
355 _GLIBCXX_NOEXCEPTnoexcept
356 : _M_node(__x) { }
357
358 _List_const_iterator(const iterator& __x) _GLIBCXX_NOEXCEPTnoexcept
359 : _M_node(__x._M_node) { }
360
361 iterator
362 _M_const_cast() const _GLIBCXX_NOEXCEPTnoexcept
363 { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); }
364
365 // Must downcast from List_node_base to _List_node to get to value.
366 _GLIBCXX_NODISCARD[[__nodiscard__]]
367 reference
368 operator*() const _GLIBCXX_NOEXCEPTnoexcept
369 { return *static_cast<_Node*>(_M_node)->_M_valptr(); }
370
371 _GLIBCXX_NODISCARD[[__nodiscard__]]
372 pointer
373 operator->() const _GLIBCXX_NOEXCEPTnoexcept
374 { return static_cast<_Node*>(_M_node)->_M_valptr(); }
375
376 _Self&
377 operator++() _GLIBCXX_NOEXCEPTnoexcept
378 {
379 _M_node = _M_node->_M_next;
380 return *this;
381 }
382
383 _Self
384 operator++(int) _GLIBCXX_NOEXCEPTnoexcept
385 {
386 _Self __tmp = *this;
387 _M_node = _M_node->_M_next;
388 return __tmp;
389 }
390
391 _Self&
392 operator--() _GLIBCXX_NOEXCEPTnoexcept
393 {
394 _M_node = _M_node->_M_prev;
395 return *this;
396 }
397
398 _Self
399 operator--(int) _GLIBCXX_NOEXCEPTnoexcept
400 {
401 _Self __tmp = *this;
402 _M_node = _M_node->_M_prev;
403 return __tmp;
404 }
405
406 _GLIBCXX_NODISCARD[[__nodiscard__]]
407 friend bool
408 operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPTnoexcept
409 { return __x._M_node == __y._M_node; }
410
411#if __cpp_impl_three_way_comparison < 201907L
412 _GLIBCXX_NODISCARD[[__nodiscard__]]
413 friend bool
414 operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPTnoexcept
415 { return __x._M_node != __y._M_node; }
416#endif
417
418 // The only member points to the %list element.
419 const __detail::_List_node_base* _M_node;
420 };
421
422_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
423 /// See bits/stl_deque.h's _Deque_base for an explanation.
424 template<typename _Tp, typename _Alloc>
425 class _List_base
426 {
427 protected:
428 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
429 rebind<_Tp>::other _Tp_alloc_type;
430 typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tp_alloc_traits;
431 typedef typename _Tp_alloc_traits::template
432 rebind<_List_node<_Tp> >::other _Node_alloc_type;
433 typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
434
435#if !_GLIBCXX_INLINE_VERSION0
436 static size_t
437 _S_distance(const __detail::_List_node_base* __first,
438 const __detail::_List_node_base* __last)
439 {
440 size_t __n = 0;
441 while (__first != __last)
442 {
443 __first = __first->_M_next;
444 ++__n;
445 }
446 return __n;
447 }
448#endif
449
450 struct _List_impl
451 : public _Node_alloc_type
452 {
453 __detail::_List_node_header _M_node;
454
455 _List_impl() _GLIBCXX_NOEXCEPT_IF(noexcept(is_nothrow_default_constructible<_Node_alloc_type
>::value)
456 is_nothrow_default_constructible<_Node_alloc_type>::value)noexcept(is_nothrow_default_constructible<_Node_alloc_type
>::value)
457 : _Node_alloc_type()
458 { }
459
460 _List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPTnoexcept
461 : _Node_alloc_type(__a)
462 { }
463
464#if __cplusplus201703L >= 201103L
465 _List_impl(_List_impl&&) = default;
466
467 _List_impl(_Node_alloc_type&& __a, _List_impl&& __x)
468 : _Node_alloc_type(std::move(__a)), _M_node(std::move(__x._M_node))
469 { }
470
471 _List_impl(_Node_alloc_type&& __a) noexcept
472 : _Node_alloc_type(std::move(__a))
473 { }
474#endif
475 };
476
477 _List_impl _M_impl;
478
479#if _GLIBCXX_USE_CXX11_ABI1
480 size_t _M_get_size() const { return _M_impl._M_node._M_size; }
481
482 void _M_set_size(size_t __n) { _M_impl._M_node._M_size = __n; }
483
484 void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; }
485
486 void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; }
487
488# if !_GLIBCXX_INLINE_VERSION0
489 size_t
490 _M_distance(const __detail::_List_node_base* __first,
491 const __detail::_List_node_base* __last) const
492 { return _S_distance(__first, __last); }
493
494 // return the stored size
495 size_t _M_node_count() const { return _M_get_size(); }
496# endif
497#else
498 // dummy implementations used when the size is not stored
499 size_t _M_get_size() const { return 0; }
500 void _M_set_size(size_t) { }
501 void _M_inc_size(size_t) { }
502 void _M_dec_size(size_t) { }
503
504# if !_GLIBCXX_INLINE_VERSION0
505 size_t _M_distance(const void*, const void*) const { return 0; }
506
507 // count the number of nodes
508 size_t _M_node_count() const
509 {
510 return _S_distance(_M_impl._M_node._M_next,
511 std::__addressof(_M_impl._M_node));
512 }
513# endif
514#endif
515
516 typename _Node_alloc_traits::pointer
517 _M_get_node()
518 { return _Node_alloc_traits::allocate(_M_impl, 1); }
519
520 void
521 _M_put_node(typename _Node_alloc_traits::pointer __p) _GLIBCXX_NOEXCEPTnoexcept
522 { _Node_alloc_traits::deallocate(_M_impl, __p, 1); }
523
524 public:
525 typedef _Alloc allocator_type;
526
527 _Node_alloc_type&
528 _M_get_Node_allocator() _GLIBCXX_NOEXCEPTnoexcept
529 { return _M_impl; }
530
531 const _Node_alloc_type&
532 _M_get_Node_allocator() const _GLIBCXX_NOEXCEPTnoexcept
533 { return _M_impl; }
534
535#if __cplusplus201703L >= 201103L
536 _List_base() = default;
537#else
538 _List_base() { }
539#endif
540
541 _List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPTnoexcept
542 : _M_impl(__a)
543 { }
544
545#if __cplusplus201703L >= 201103L
546 _List_base(_List_base&&) = default;
547
548# if !_GLIBCXX_INLINE_VERSION0
549 _List_base(_List_base&& __x, _Node_alloc_type&& __a)
550 : _M_impl(std::move(__a))
551 {
552 if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
553 _M_move_nodes(std::move(__x));
554 // else caller must move individual elements.
555 }
556# endif
557
558 // Used when allocator is_always_equal.
559 _List_base(_Node_alloc_type&& __a, _List_base&& __x)
560 : _M_impl(std::move(__a), std::move(__x._M_impl))
561 { }
562
563 // Used when allocator !is_always_equal.
564 _List_base(_Node_alloc_type&& __a)
565 : _M_impl(std::move(__a))
566 { }
567
568 void
569 _M_move_nodes(_List_base&& __x)
570 { _M_impl._M_node._M_move_nodes(std::move(__x._M_impl._M_node)); }
571#endif
572
573 // This is what actually destroys the list.
574 ~_List_base() _GLIBCXX_NOEXCEPTnoexcept
575 { _M_clear(); }
576
577 void
578 _M_clear() _GLIBCXX_NOEXCEPTnoexcept;
579
580 void
581 _M_init() _GLIBCXX_NOEXCEPTnoexcept
582 { this->_M_impl._M_node._M_init(); }
583 };
584
585 /**
586 * @brief A standard container with linear time access to elements,
587 * and fixed time insertion/deletion at any point in the sequence.
588 *
589 * @ingroup sequences
590 *
591 * @tparam _Tp Type of element.
592 * @tparam _Alloc Allocator type, defaults to allocator<_Tp>.
593 *
594 * Meets the requirements of a <a href="tables.html#65">container</a>, a
595 * <a href="tables.html#66">reversible container</a>, and a
596 * <a href="tables.html#67">sequence</a>, including the
597 * <a href="tables.html#68">optional sequence requirements</a> with the
598 * %exception of @c at and @c operator[].
599 *
600 * This is a @e doubly @e linked %list. Traversal up and down the
601 * %list requires linear time, but adding and removing elements (or
602 * @e nodes) is done in constant time, regardless of where the
603 * change takes place. Unlike std::vector and std::deque,
604 * random-access iterators are not provided, so subscripting ( @c
605 * [] ) access is not allowed. For algorithms which only need
606 * sequential access, this lack makes no difference.
607 *
608 * Also unlike the other standard containers, std::list provides
609 * specialized algorithms %unique to linked lists, such as
610 * splicing, sorting, and in-place reversal.
611 *
612 * A couple points on memory allocation for list<Tp>:
613 *
614 * First, we never actually allocate a Tp, we allocate
615 * List_node<Tp>'s and trust [20.1.5]/4 to DTRT. This is to ensure
616 * that after elements from %list<X,Alloc1> are spliced into
617 * %list<X,Alloc2>, destroying the memory of the second %list is a
618 * valid operation, i.e., Alloc1 giveth and Alloc2 taketh away.
619 *
620 * Second, a %list conceptually represented as
621 * @code
622 * A <---> B <---> C <---> D
623 * @endcode
624 * is actually circular; a link exists between A and D. The %list
625 * class holds (as its only data member) a private list::iterator
626 * pointing to @e D, not to @e A! To get to the head of the %list,
627 * we start at the tail and move forward by one. When this member
628 * iterator's next/previous pointers refer to itself, the %list is
629 * %empty.
630 */
631 template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
632 class list : protected _List_base<_Tp, _Alloc>
633 {
634#ifdef _GLIBCXX_CONCEPT_CHECKS
635 // concept requirements
636 typedef typename _Alloc::value_type _Alloc_value_type;
637# if __cplusplus201703L < 201103L
638 __glibcxx_class_requires(_Tp, _SGIAssignableConcept)
639# endif
640 __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept)
641#endif
642
643#if __cplusplus201703L >= 201103L
644 static_assert(is_same<typename remove_cv<_Tp>::type, _Tp>::value,
645 "std::list must have a non-const, non-volatile value_type");
646# if __cplusplus201703L > 201703L || defined __STRICT_ANSI__
647 static_assert(is_same<typename _Alloc::value_type, _Tp>::value,
648 "std::list must have the same value_type as its allocator");
649# endif
650#endif
651
652 typedef _List_base<_Tp, _Alloc> _Base;
653 typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
654 typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits;
655 typedef typename _Base::_Node_alloc_type _Node_alloc_type;
656 typedef typename _Base::_Node_alloc_traits _Node_alloc_traits;
657
658 public:
659 typedef _Tp value_type;
660 typedef typename _Tp_alloc_traits::pointer pointer;
661 typedef typename _Tp_alloc_traits::const_pointer const_pointer;
662 typedef typename _Tp_alloc_traits::reference reference;
663 typedef typename _Tp_alloc_traits::const_reference const_reference;
664 typedef _List_iterator<_Tp> iterator;
665 typedef _List_const_iterator<_Tp> const_iterator;
666 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
667 typedef std::reverse_iterator<iterator> reverse_iterator;
668 typedef size_t size_type;
669 typedef ptrdiff_t difference_type;
670 typedef _Alloc allocator_type;
671
672 protected:
673 // Note that pointers-to-_Node's can be ctor-converted to
674 // iterator types.
675 typedef _List_node<_Tp> _Node;
676
677 using _Base::_M_impl;
678 using _Base::_M_put_node;
679 using _Base::_M_get_node;
680 using _Base::_M_get_Node_allocator;
681
682 /**
683 * @param __args An instance of user data.
684 *
685 * Allocates space for a new node and constructs a copy of
686 * @a __args in it.
687 */
688#if __cplusplus201703L < 201103L
689 _Node*
690 _M_create_node(const value_type& __x)
691 {
692 _Node* __p = this->_M_get_node();
693 __trytry
694 {
695 _Tp_alloc_type __alloc(_M_get_Node_allocator());
696 __alloc.construct(__p->_M_valptr(), __x);
697 }
698 __catch(...)catch(...)
699 {
700 _M_put_node(__p);
701 __throw_exception_againthrow;
702 }
703 return __p;
704 }
705#else
706 template<typename... _Args>
707 _Node*
708 _M_create_node(_Args&&... __args)
709 {
710 auto __p = this->_M_get_node();
711 auto& __alloc = _M_get_Node_allocator();
712 __allocated_ptr<_Node_alloc_type> __guard{__alloc, __p};
713 _Node_alloc_traits::construct(__alloc, __p->_M_valptr(),
714 std::forward<_Args>(__args)...);
715 __guard = nullptr;
716 return __p;
717 }
718#endif
719
720#if _GLIBCXX_USE_CXX11_ABI1
721 static size_t
722 _S_distance(const_iterator __first, const_iterator __last)
723 { return std::distance(__first, __last); }
724
725 // return the stored size
726 size_t
727 _M_node_count() const
728 { return this->_M_get_size(); }
729#else
730 // dummy implementations used when the size is not stored
731 static size_t
732 _S_distance(const_iterator, const_iterator)
733 { return 0; }
734
735 // count the number of nodes
736 size_t
737 _M_node_count() const
738 { return std::distance(begin(), end()); }
739#endif
740
741 public:
742 // [23.2.2.1] construct/copy/destroy
743 // (assign() and get_allocator() are also listed in this section)
744
745 /**
746 * @brief Creates a %list with no elements.
747 */
748#if __cplusplus201703L >= 201103L
749 list() = default;
750#else
751 list() { }
752#endif
753
754 /**
755 * @brief Creates a %list with no elements.
756 * @param __a An allocator object.
757 */
758 explicit
759 list(const allocator_type& __a) _GLIBCXX_NOEXCEPTnoexcept
760 : _Base(_Node_alloc_type(__a)) { }
761
762#if __cplusplus201703L >= 201103L
763 /**
764 * @brief Creates a %list with default constructed elements.
765 * @param __n The number of elements to initially create.
766 * @param __a An allocator object.
767 *
768 * This constructor fills the %list with @a __n default
769 * constructed elements.
770 */
771 explicit
772 list(size_type __n, const allocator_type& __a = allocator_type())
773 : _Base(_Node_alloc_type(__a))
774 { _M_default_initialize(__n); }
775
776 /**
777 * @brief Creates a %list with copies of an exemplar element.
778 * @param __n The number of elements to initially create.
779 * @param __value An element to copy.
780 * @param __a An allocator object.
781 *
782 * This constructor fills the %list with @a __n copies of @a __value.
783 */
784 list(size_type __n, const value_type& __value,
785 const allocator_type& __a = allocator_type())
786 : _Base(_Node_alloc_type(__a))
787 { _M_fill_initialize(__n, __value); }
788#else
789 /**
790 * @brief Creates a %list with copies of an exemplar element.
791 * @param __n The number of elements to initially create.
792 * @param __value An element to copy.
793 * @param __a An allocator object.
794 *
795 * This constructor fills the %list with @a __n copies of @a __value.
796 */
797 explicit
798 list(size_type __n, const value_type& __value = value_type(),
799 const allocator_type& __a = allocator_type())
800 : _Base(_Node_alloc_type(__a))
801 { _M_fill_initialize(__n, __value); }
802#endif
803
804 /**
805 * @brief %List copy constructor.
806 * @param __x A %list of identical element and allocator types.
807 *
808 * The newly-created %list uses a copy of the allocation object used
809 * by @a __x (unless the allocator traits dictate a different object).
810 */
811 list(const list& __x)
812 : _Base(_Node_alloc_traits::
813 _S_select_on_copy(__x._M_get_Node_allocator()))
814 { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
815
816#if __cplusplus201703L >= 201103L
817 /**
818 * @brief %List move constructor.
819 *
820 * The newly-created %list contains the exact contents of the moved
821 * instance. The contents of the moved instance are a valid, but
822 * unspecified %list.
823 */
824 list(list&&) = default;
825
826 /**
827 * @brief Builds a %list from an initializer_list
828 * @param __l An initializer_list of value_type.
829 * @param __a An allocator object.
830 *
831 * Create a %list consisting of copies of the elements in the
832 * initializer_list @a __l. This is linear in __l.size().
833 */
834 list(initializer_list<value_type> __l,
835 const allocator_type& __a = allocator_type())
836 : _Base(_Node_alloc_type(__a))
837 { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); }
838
839 list(const list& __x, const __type_identity_t<allocator_type>& __a)
840 : _Base(_Node_alloc_type(__a))
841 { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
842
843 private:
844 list(list&& __x, const allocator_type& __a, true_type) noexcept
845 : _Base(_Node_alloc_type(__a), std::move(__x))
846 { }
847
848 list(list&& __x, const allocator_type& __a, false_type)
849 : _Base(_Node_alloc_type(__a))
850 {
851 if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator())
852 this->_M_move_nodes(std::move(__x));
853 else
854 insert(begin(), std::__make_move_if_noexcept_iterator(__x.begin()),
855 std::__make_move_if_noexcept_iterator(__x.end()));
856 }
857
858 public:
859 list(list&& __x, const __type_identity_t<allocator_type>& __a)
860 noexcept(_Node_alloc_traits::_S_always_equal())
861 : list(std::move(__x), __a,
862 typename _Node_alloc_traits::is_always_equal{})
863 { }
864#endif
865
866 /**
867 * @brief Builds a %list from a range.
868 * @param __first An input iterator.
869 * @param __last An input iterator.
870 * @param __a An allocator object.
871 *
872 * Create a %list consisting of copies of the elements from
873 * [@a __first,@a __last). This is linear in N (where N is
874 * distance(@a __first,@a __last)).
875 */
876#if __cplusplus201703L >= 201103L
877 template<typename _InputIterator,
878 typename = std::_RequireInputIter<_InputIterator>>
879 list(_InputIterator __first, _InputIterator __last,
880 const allocator_type& __a = allocator_type())
881 : _Base(_Node_alloc_type(__a))
882 { _M_initialize_dispatch(__first, __last, __false_type()); }
883#else
884 template<typename _InputIterator>
885 list(_InputIterator __first, _InputIterator __last,
886 const allocator_type& __a = allocator_type())
887 : _Base(_Node_alloc_type(__a))
888 {
889 // Check whether it's an integral type. If so, it's not an iterator.
890 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
891 _M_initialize_dispatch(__first, __last, _Integral());
892 }
893#endif
894
895#if __cplusplus201703L >= 201103L
896 /**
897 * No explicit dtor needed as the _Base dtor takes care of
898 * things. The _Base dtor only erases the elements, and note
899 * that if the elements themselves are pointers, the pointed-to
900 * memory is not touched in any way. Managing the pointer is
901 * the user's responsibility.
902 */
903 ~list() = default;
904#endif
905
906 /**
907 * @brief %List assignment operator.
908 * @param __x A %list of identical element and allocator types.
909 *
910 * All the elements of @a __x are copied.
911 *
912 * Whether the allocator is copied depends on the allocator traits.
913 */
914 list&
915 operator=(const list& __x);
916
917#if __cplusplus201703L >= 201103L
918 /**
919 * @brief %List move assignment operator.
920 * @param __x A %list of identical element and allocator types.
921 *
922 * The contents of @a __x are moved into this %list (without copying).
923 *
924 * Afterwards @a __x is a valid, but unspecified %list
925 *
926 * Whether the allocator is moved depends on the allocator traits.
927 */
928 list&
929 operator=(list&& __x)
930 noexcept(_Node_alloc_traits::_S_nothrow_move())
931 {
932 constexpr bool __move_storage =
933 _Node_alloc_traits::_S_propagate_on_move_assign()
934 || _Node_alloc_traits::_S_always_equal();
935 _M_move_assign(std::move(__x), __bool_constant<__move_storage>());
936 return *this;
937 }
938
939 /**
940 * @brief %List initializer list assignment operator.
941 * @param __l An initializer_list of value_type.
942 *
943 * Replace the contents of the %list with copies of the elements
944 * in the initializer_list @a __l. This is linear in l.size().
945 */
946 list&
947 operator=(initializer_list<value_type> __l)
948 {
949 this->assign(__l.begin(), __l.end());
950 return *this;
951 }
952#endif
953
954 /**
955 * @brief Assigns a given value to a %list.
956 * @param __n Number of elements to be assigned.
957 * @param __val Value to be assigned.
958 *
959 * This function fills a %list with @a __n copies of the given
960 * value. Note that the assignment completely changes the %list
961 * and that the resulting %list's size is the same as the number
962 * of elements assigned.
963 */
964 void
965 assign(size_type __n, const value_type& __val)
966 { _M_fill_assign(__n, __val); }
967
968 /**
969 * @brief Assigns a range to a %list.
970 * @param __first An input iterator.
971 * @param __last An input iterator.
972 *
973 * This function fills a %list with copies of the elements in the
974 * range [@a __first,@a __last).
975 *
976 * Note that the assignment completely changes the %list and
977 * that the resulting %list's size is the same as the number of
978 * elements assigned.
979 */
980#if __cplusplus201703L >= 201103L
981 template<typename _InputIterator,
982 typename = std::_RequireInputIter<_InputIterator>>
983 void
984 assign(_InputIterator __first, _InputIterator __last)
985 { _M_assign_dispatch(__first, __last, __false_type()); }
986#else
987 template<typename _InputIterator>
988 void
989 assign(_InputIterator __first, _InputIterator __last)
990 {
991 // Check whether it's an integral type. If so, it's not an iterator.
992 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
993 _M_assign_dispatch(__first, __last, _Integral());
994 }
995#endif
996
997#if __cplusplus201703L >= 201103L
998 /**
999 * @brief Assigns an initializer_list to a %list.
1000 * @param __l An initializer_list of value_type.
1001 *
1002 * Replace the contents of the %list with copies of the elements
1003 * in the initializer_list @a __l. This is linear in __l.size().
1004 */
1005 void
1006 assign(initializer_list<value_type> __l)
1007 { this->_M_assign_dispatch(__l.begin(), __l.end(), __false_type()); }
1008#endif
1009
1010 /// Get a copy of the memory allocation object.
1011 allocator_type
1012 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
1013 { return allocator_type(_Base::_M_get_Node_allocator()); }
1014
1015 // iterators
1016 /**
1017 * Returns a read/write iterator that points to the first element in the
1018 * %list. Iteration is done in ordinary element order.
1019 */
1020 _GLIBCXX_NODISCARD[[__nodiscard__]]
1021 iterator
1022 begin() _GLIBCXX_NOEXCEPTnoexcept
1023 { return iterator(this->_M_impl._M_node._M_next); }
1024
1025 /**
1026 * Returns a read-only (constant) iterator that points to the
1027 * first element in the %list. Iteration is done in ordinary
1028 * element order.
1029 */
1030 _GLIBCXX_NODISCARD[[__nodiscard__]]
1031 const_iterator
1032 begin() const _GLIBCXX_NOEXCEPTnoexcept
1033 { return const_iterator(this->_M_impl._M_node._M_next); }
1034
1035 /**
1036 * Returns a read/write iterator that points one past the last
1037 * element in the %list. Iteration is done in ordinary element
1038 * order.
1039 */
1040 _GLIBCXX_NODISCARD[[__nodiscard__]]
1041 iterator
1042 end() _GLIBCXX_NOEXCEPTnoexcept
1043 { return iterator(&this->_M_impl._M_node); }
1044
1045 /**
1046 * Returns a read-only (constant) iterator that points one past
1047 * the last element in the %list. Iteration is done in ordinary
1048 * element order.
1049 */
1050 _GLIBCXX_NODISCARD[[__nodiscard__]]
1051 const_iterator
1052 end() const _GLIBCXX_NOEXCEPTnoexcept
1053 { return const_iterator(&this->_M_impl._M_node); }
1054
1055 /**
1056 * Returns a read/write reverse iterator that points to the last
1057 * element in the %list. Iteration is done in reverse element
1058 * order.
1059 */
1060 _GLIBCXX_NODISCARD[[__nodiscard__]]
1061 reverse_iterator
1062 rbegin() _GLIBCXX_NOEXCEPTnoexcept
1063 { return reverse_iterator(end()); }
1064
1065 /**
1066 * Returns a read-only (constant) reverse iterator that points to
1067 * the last element in the %list. Iteration is done in reverse
1068 * element order.
1069 */
1070 _GLIBCXX_NODISCARD[[__nodiscard__]]
1071 const_reverse_iterator
1072 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
1073 { return const_reverse_iterator(end()); }
1074
1075 /**
1076 * Returns a read/write reverse iterator that points to one
1077 * before the first element in the %list. Iteration is done in
1078 * reverse element order.
1079 */
1080 _GLIBCXX_NODISCARD[[__nodiscard__]]
1081 reverse_iterator
1082 rend() _GLIBCXX_NOEXCEPTnoexcept
1083 { return reverse_iterator(begin()); }
1084
1085 /**
1086 * Returns a read-only (constant) reverse iterator that points to one
1087 * before the first element in the %list. Iteration is done in reverse
1088 * element order.
1089 */
1090 _GLIBCXX_NODISCARD[[__nodiscard__]]
1091 const_reverse_iterator
1092 rend() const _GLIBCXX_NOEXCEPTnoexcept
1093 { return const_reverse_iterator(begin()); }
1094
1095#if __cplusplus201703L >= 201103L
1096 /**
1097 * Returns a read-only (constant) iterator that points to the
1098 * first element in the %list. Iteration is done in ordinary
1099 * element order.
1100 */
1101 [[__nodiscard__]]
1102 const_iterator
1103 cbegin() const noexcept
1104 { return const_iterator(this->_M_impl._M_node._M_next); }
1105
1106 /**
1107 * Returns a read-only (constant) iterator that points one past
1108 * the last element in the %list. Iteration is done in ordinary
1109 * element order.
1110 */
1111 [[__nodiscard__]]
1112 const_iterator
1113 cend() const noexcept
1114 { return const_iterator(&this->_M_impl._M_node); }
1115
1116 /**
1117 * Returns a read-only (constant) reverse iterator that points to
1118 * the last element in the %list. Iteration is done in reverse
1119 * element order.
1120 */
1121 [[__nodiscard__]]
1122 const_reverse_iterator
1123 crbegin() const noexcept
1124 { return const_reverse_iterator(end()); }
1125
1126 /**
1127 * Returns a read-only (constant) reverse iterator that points to one
1128 * before the first element in the %list. Iteration is done in reverse
1129 * element order.
1130 */
1131 [[__nodiscard__]]
1132 const_reverse_iterator
1133 crend() const noexcept
1134 { return const_reverse_iterator(begin()); }
1135#endif
1136
1137 // [23.2.2.2] capacity
1138 /**
1139 * Returns true if the %list is empty. (Thus begin() would equal
1140 * end().)
1141 */
1142 _GLIBCXX_NODISCARD[[__nodiscard__]] bool
1143 empty() const _GLIBCXX_NOEXCEPTnoexcept
1144 { return this->_M_impl._M_node._M_next == &this->_M_impl._M_node; }
1145
1146 /** Returns the number of elements in the %list. */
1147 _GLIBCXX_NODISCARD[[__nodiscard__]]
1148 size_type
1149 size() const _GLIBCXX_NOEXCEPTnoexcept
1150 { return _M_node_count(); }
1151
1152 /** Returns the size() of the largest possible %list. */
1153 _GLIBCXX_NODISCARD[[__nodiscard__]]
1154 size_type
1155 max_size() const _GLIBCXX_NOEXCEPTnoexcept
1156 { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); }
1157
1158#if __cplusplus201703L >= 201103L
1159 /**
1160 * @brief Resizes the %list to the specified number of elements.
1161 * @param __new_size Number of elements the %list should contain.
1162 *
1163 * This function will %resize the %list to the specified number
1164 * of elements. If the number is smaller than the %list's
1165 * current size the %list is truncated, otherwise default
1166 * constructed elements are appended.
1167 */
1168 void
1169 resize(size_type __new_size);
1170
1171 /**
1172 * @brief Resizes the %list to the specified number of elements.
1173 * @param __new_size Number of elements the %list should contain.
1174 * @param __x Data with which new elements should be populated.
1175 *
1176 * This function will %resize the %list to the specified number
1177 * of elements. If the number is smaller than the %list's
1178 * current size the %list is truncated, otherwise the %list is
1179 * extended and new elements are populated with given data.
1180 */
1181 void
1182 resize(size_type __new_size, const value_type& __x);
1183#else
1184 /**
1185 * @brief Resizes the %list to the specified number of elements.
1186 * @param __new_size Number of elements the %list should contain.
1187 * @param __x Data with which new elements should be populated.
1188 *
1189 * This function will %resize the %list to the specified number
1190 * of elements. If the number is smaller than the %list's
1191 * current size the %list is truncated, otherwise the %list is
1192 * extended and new elements are populated with given data.
1193 */
1194 void
1195 resize(size_type __new_size, value_type __x = value_type());
1196#endif
1197
1198 // element access
1199 /**
1200 * Returns a read/write reference to the data at the first
1201 * element of the %list.
1202 */
1203 _GLIBCXX_NODISCARD[[__nodiscard__]]
1204 reference
1205 front() _GLIBCXX_NOEXCEPTnoexcept
1206 { return *begin(); }
1207
1208 /**
1209 * Returns a read-only (constant) reference to the data at the first
1210 * element of the %list.
1211 */
1212 _GLIBCXX_NODISCARD[[__nodiscard__]]
1213 const_reference
1214 front() const _GLIBCXX_NOEXCEPTnoexcept
1215 { return *begin(); }
1216
1217 /**
1218 * Returns a read/write reference to the data at the last element
1219 * of the %list.
1220 */
1221 _GLIBCXX_NODISCARD[[__nodiscard__]]
1222 reference
1223 back() _GLIBCXX_NOEXCEPTnoexcept
1224 {
1225 iterator __tmp = end();
1226 --__tmp;
1227 return *__tmp;
1228 }
1229
1230 /**
1231 * Returns a read-only (constant) reference to the data at the last
1232 * element of the %list.
1233 */
1234 _GLIBCXX_NODISCARD[[__nodiscard__]]
1235 const_reference
1236 back() const _GLIBCXX_NOEXCEPTnoexcept
1237 {
1238 const_iterator __tmp = end();
1239 --__tmp;
1240 return *__tmp;
1241 }
1242
1243 // [23.2.2.3] modifiers
1244 /**
1245 * @brief Add data to the front of the %list.
1246 * @param __x Data to be added.
1247 *
1248 * This is a typical stack operation. The function creates an
1249 * element at the front of the %list and assigns the given data
1250 * to it. Due to the nature of a %list this operation can be
1251 * done in constant time, and does not invalidate iterators and
1252 * references.
1253 */
1254 void
1255 push_front(const value_type& __x)
1256 { this->_M_insert(begin(), __x); }
1257
1258#if __cplusplus201703L >= 201103L
1259 void
1260 push_front(value_type&& __x)
1261 { this->_M_insert(begin(), std::move(__x)); }
1262
1263 template<typename... _Args>
1264#if __cplusplus201703L > 201402L
1265 reference
1266#else
1267 void
1268#endif
1269 emplace_front(_Args&&... __args)
1270 {
1271 this->_M_insert(begin(), std::forward<_Args>(__args)...);
1272#if __cplusplus201703L > 201402L
1273 return front();
1274#endif
1275 }
1276#endif
1277
1278 /**
1279 * @brief Removes first element.
1280 *
1281 * This is a typical stack operation. It shrinks the %list by
1282 * one. Due to the nature of a %list this operation can be done
1283 * in constant time, and only invalidates iterators/references to
1284 * the element being removed.
1285 *
1286 * Note that no data is returned, and if the first element's data
1287 * is needed, it should be retrieved before pop_front() is
1288 * called.
1289 */
1290 void
1291 pop_front() _GLIBCXX_NOEXCEPTnoexcept
1292 { this->_M_erase(begin()); }
1293
1294 /**
1295 * @brief Add data to the end of the %list.
1296 * @param __x Data to be added.
1297 *
1298 * This is a typical stack operation. The function creates an
1299 * element at the end of the %list and assigns the given data to
1300 * it. Due to the nature of a %list this operation can be done
1301 * in constant time, and does not invalidate iterators and
1302 * references.
1303 */
1304 void
1305 push_back(const value_type& __x)
1306 { this->_M_insert(end(), __x); }
1307
1308#if __cplusplus201703L >= 201103L
1309 void
1310 push_back(value_type&& __x)
1311 { this->_M_insert(end(), std::move(__x)); }
1312
1313 template<typename... _Args>
1314#if __cplusplus201703L > 201402L
1315 reference
1316#else
1317 void
1318#endif
1319 emplace_back(_Args&&... __args)
1320 {
1321 this->_M_insert(end(), std::forward<_Args>(__args)...);
1322#if __cplusplus201703L > 201402L
1323 return back();
1324#endif
1325 }
1326#endif
1327
1328 /**
1329 * @brief Removes last element.
1330 *
1331 * This is a typical stack operation. It shrinks the %list by
1332 * one. Due to the nature of a %list this operation can be done
1333 * in constant time, and only invalidates iterators/references to
1334 * the element being removed.
1335 *
1336 * Note that no data is returned, and if the last element's data
1337 * is needed, it should be retrieved before pop_back() is called.
1338 */
1339 void
1340 pop_back() _GLIBCXX_NOEXCEPTnoexcept
1341 { this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); }
1342
1343#if __cplusplus201703L >= 201103L
1344 /**
1345 * @brief Constructs object in %list before specified iterator.
1346 * @param __position A const_iterator into the %list.
1347 * @param __args Arguments.
1348 * @return An iterator that points to the inserted data.
1349 *
1350 * This function will insert an object of type T constructed
1351 * with T(std::forward<Args>(args)...) before the specified
1352 * location. Due to the nature of a %list this operation can
1353 * be done in constant time, and does not invalidate iterators
1354 * and references.
1355 */
1356 template<typename... _Args>
1357 iterator
1358 emplace(const_iterator __position, _Args&&... __args);
1359
1360 /**
1361 * @brief Inserts given value into %list before specified iterator.
1362 * @param __position A const_iterator into the %list.
1363 * @param __x Data to be inserted.
1364 * @return An iterator that points to the inserted data.
1365 *
1366 * This function will insert a copy of the given value before
1367 * the specified location. Due to the nature of a %list this
1368 * operation can be done in constant time, and does not
1369 * invalidate iterators and references.
1370 */
1371 iterator
1372 insert(const_iterator __position, const value_type& __x);
1373#else
1374 /**
1375 * @brief Inserts given value into %list before specified iterator.
1376 * @param __position An iterator into the %list.
1377 * @param __x Data to be inserted.
1378 * @return An iterator that points to the inserted data.
1379 *
1380 * This function will insert a copy of the given value before
1381 * the specified location. Due to the nature of a %list this
1382 * operation can be done in constant time, and does not
1383 * invalidate iterators and references.
1384 */
1385 iterator
1386 insert(iterator __position, const value_type& __x);
1387#endif
1388
1389#if __cplusplus201703L >= 201103L
1390 /**
1391 * @brief Inserts given rvalue into %list before specified iterator.
1392 * @param __position A const_iterator into the %list.
1393 * @param __x Data to be inserted.
1394 * @return An iterator that points to the inserted data.
1395 *
1396 * This function will insert a copy of the given rvalue before
1397 * the specified location. Due to the nature of a %list this
1398 * operation can be done in constant time, and does not
1399 * invalidate iterators and references.
1400 */
1401 iterator
1402 insert(const_iterator __position, value_type&& __x)
1403 { return emplace(__position, std::move(__x)); }
1404
1405 /**
1406 * @brief Inserts the contents of an initializer_list into %list
1407 * before specified const_iterator.
1408 * @param __p A const_iterator into the %list.
1409 * @param __l An initializer_list of value_type.
1410 * @return An iterator pointing to the first element inserted
1411 * (or __position).
1412 *
1413 * This function will insert copies of the data in the
1414 * initializer_list @a l into the %list before the location
1415 * specified by @a p.
1416 *
1417 * This operation is linear in the number of elements inserted and
1418 * does not invalidate iterators and references.
1419 */
1420 iterator
1421 insert(const_iterator __p, initializer_list<value_type> __l)
1422 { return this->insert(__p, __l.begin(), __l.end()); }
1423#endif
1424
1425#if __cplusplus201703L >= 201103L
1426 /**
1427 * @brief Inserts a number of copies of given data into the %list.
1428 * @param __position A const_iterator into the %list.
1429 * @param __n Number of elements to be inserted.
1430 * @param __x Data to be inserted.
1431 * @return An iterator pointing to the first element inserted
1432 * (or __position).
1433 *
1434 * This function will insert a specified number of copies of the
1435 * given data before the location specified by @a position.
1436 *
1437 * This operation is linear in the number of elements inserted and
1438 * does not invalidate iterators and references.
1439 */
1440 iterator
1441 insert(const_iterator __position, size_type __n, const value_type& __x);
1442#else
1443 /**
1444 * @brief Inserts a number of copies of given data into the %list.
1445 * @param __position An iterator into the %list.
1446 * @param __n Number of elements to be inserted.
1447 * @param __x Data to be inserted.
1448 *
1449 * This function will insert a specified number of copies of the
1450 * given data before the location specified by @a position.
1451 *
1452 * This operation is linear in the number of elements inserted and
1453 * does not invalidate iterators and references.
1454 */
1455 void
1456 insert(iterator __position, size_type __n, const value_type& __x)
1457 {
1458 list __tmp(__n, __x, get_allocator());
1459 splice(__position, __tmp);
1460 }
1461#endif
1462
1463#if __cplusplus201703L >= 201103L
1464 /**
1465 * @brief Inserts a range into the %list.
1466 * @param __position A const_iterator into the %list.
1467 * @param __first An input iterator.
1468 * @param __last An input iterator.
1469 * @return An iterator pointing to the first element inserted
1470 * (or __position).
1471 *
1472 * This function will insert copies of the data in the range [@a
1473 * first,@a last) into the %list before the location specified by
1474 * @a position.
1475 *
1476 * This operation is linear in the number of elements inserted and
1477 * does not invalidate iterators and references.
1478 */
1479 template<typename _InputIterator,
1480 typename = std::_RequireInputIter<_InputIterator>>
1481 iterator
1482 insert(const_iterator __position, _InputIterator __first,
1483 _InputIterator __last);
1484#else
1485 /**
1486 * @brief Inserts a range into the %list.
1487 * @param __position An iterator into the %list.
1488 * @param __first An input iterator.
1489 * @param __last An input iterator.
1490 *
1491 * This function will insert copies of the data in the range [@a
1492 * first,@a last) into the %list before the location specified by
1493 * @a position.
1494 *
1495 * This operation is linear in the number of elements inserted and
1496 * does not invalidate iterators and references.
1497 */
1498 template<typename _InputIterator>
1499 void
1500 insert(iterator __position, _InputIterator __first,
1501 _InputIterator __last)
1502 {
1503 list __tmp(__first, __last, get_allocator());
1504 splice(__position, __tmp);
1505 }
1506#endif
1507
1508 /**
1509 * @brief Remove element at given position.
1510 * @param __position Iterator pointing to element to be erased.
1511 * @return An iterator pointing to the next element (or end()).
1512 *
1513 * This function will erase the element at the given position and thus
1514 * shorten the %list by one.
1515 *
1516 * Due to the nature of a %list this operation can be done in
1517 * constant time, and only invalidates iterators/references to
1518 * the element being removed. The user is also cautioned that
1519 * this function only erases the element, and that if the element
1520 * is itself a pointer, the pointed-to memory is not touched in
1521 * any way. Managing the pointer is the user's responsibility.
1522 */
1523 iterator
1524#if __cplusplus201703L >= 201103L
1525 erase(const_iterator __position) noexcept;
1526#else
1527 erase(iterator __position);
1528#endif
1529
1530 /**
1531 * @brief Remove a range of elements.
1532 * @param __first Iterator pointing to the first element to be erased.
1533 * @param __last Iterator pointing to one past the last element to be
1534 * erased.
1535 * @return An iterator pointing to the element pointed to by @a last
1536 * prior to erasing (or end()).
1537 *
1538 * This function will erase the elements in the range @a
1539 * [first,last) and shorten the %list accordingly.
1540 *
1541 * This operation is linear time in the size of the range and only
1542 * invalidates iterators/references to the element being removed.
1543 * The user is also cautioned that this function only erases the
1544 * elements, and that if the elements themselves are pointers, the
1545 * pointed-to memory is not touched in any way. Managing the pointer
1546 * is the user's responsibility.
1547 */
1548 iterator
1549#if __cplusplus201703L >= 201103L
1550 erase(const_iterator __first, const_iterator __last) noexcept
1551#else
1552 erase(iterator __first, iterator __last)
1553#endif
1554 {
1555 while (__first != __last)
1556 __first = erase(__first);
1557 return __last._M_const_cast();
1558 }
1559
1560 /**
1561 * @brief Swaps data with another %list.
1562 * @param __x A %list of the same element and allocator types.
1563 *
1564 * This exchanges the elements between two lists in constant
1565 * time. Note that the global std::swap() function is
1566 * specialized such that std::swap(l1,l2) will feed to this
1567 * function.
1568 *
1569 * Whether the allocators are swapped depends on the allocator traits.
1570 */
1571 void
1572 swap(list& __x) _GLIBCXX_NOEXCEPTnoexcept
1573 {
1574 __detail::_List_node_base::swap(this->_M_impl._M_node,
1575 __x._M_impl._M_node);
1576
1577 size_t __xsize = __x._M_get_size();
1578 __x._M_set_size(this->_M_get_size());
1579 this->_M_set_size(__xsize);
1580
1581 _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(),
1582 __x._M_get_Node_allocator());
1583 }
1584
1585 /**
1586 * Erases all the elements. Note that this function only erases
1587 * the elements, and that if the elements themselves are
1588 * pointers, the pointed-to memory is not touched in any way.
1589 * Managing the pointer is the user's responsibility.
1590 */
1591 void
1592 clear() _GLIBCXX_NOEXCEPTnoexcept
1593 {
1594 _Base::_M_clear();
1595 _Base::_M_init();
1596 }
1597
1598 // [23.2.2.4] list operations
1599 /**
1600 * @brief Insert contents of another %list.
1601 * @param __position Iterator referencing the element to insert before.
1602 * @param __x Source list.
1603 *
1604 * The elements of @a __x are inserted in constant time in front of
1605 * the element referenced by @a __position. @a __x becomes an empty
1606 * list.
1607 *
1608 * Requires this != @a __x.
1609 */
1610 void
1611#if __cplusplus201703L >= 201103L
1612 splice(const_iterator __position, list&& __x) noexcept
1613#else
1614 splice(iterator __position, list& __x)
1615#endif
1616 {
1617 if (!__x.empty())
1618 {
1619 _M_check_equal_allocators(__x);
1620
1621 this->_M_transfer(__position._M_const_cast(),
1622 __x.begin(), __x.end());
1623
1624 this->_M_inc_size(__x._M_get_size());
1625 __x._M_set_size(0);
1626 }
1627 }
1628
1629#if __cplusplus201703L >= 201103L
1630 void
1631 splice(const_iterator __position, list& __x) noexcept
1632 { splice(__position, std::move(__x)); }
1633#endif
1634
1635#if __cplusplus201703L >= 201103L
1636 /**
1637 * @brief Insert element from another %list.
1638 * @param __position Const_iterator referencing the element to
1639 * insert before.
1640 * @param __x Source list.
1641 * @param __i Const_iterator referencing the element to move.
1642 *
1643 * Removes the element in list @a __x referenced by @a __i and
1644 * inserts it into the current list before @a __position.
1645 */
1646 void
1647 splice(const_iterator __position, list&& __x, const_iterator __i) noexcept
1648#else
1649 /**
1650 * @brief Insert element from another %list.
1651 * @param __position Iterator referencing the element to insert before.
1652 * @param __x Source list.
1653 * @param __i Iterator referencing the element to move.
1654 *
1655 * Removes the element in list @a __x referenced by @a __i and
1656 * inserts it into the current list before @a __position.
1657 */
1658 void
1659 splice(iterator __position, list& __x, iterator __i)
1660#endif
1661 {
1662 iterator __j = __i._M_const_cast();
1663 ++__j;
1664 if (__position == __i || __position == __j)
1665 return;
1666
1667 if (this != std::__addressof(__x))
1668 _M_check_equal_allocators(__x);
1669
1670 this->_M_transfer(__position._M_const_cast(),
1671 __i._M_const_cast(), __j);
1672
1673 this->_M_inc_size(1);
1674 __x._M_dec_size(1);
1675 }
1676
1677#if __cplusplus201703L >= 201103L
1678 /**
1679 * @brief Insert element from another %list.
1680 * @param __position Const_iterator referencing the element to
1681 * insert before.
1682 * @param __x Source list.
1683 * @param __i Const_iterator referencing the element to move.
1684 *
1685 * Removes the element in list @a __x referenced by @a __i and
1686 * inserts it into the current list before @a __position.
1687 */
1688 void
1689 splice(const_iterator __position, list& __x, const_iterator __i) noexcept
1690 { splice(__position, std::move(__x), __i); }
1691#endif
1692
1693#if __cplusplus201703L >= 201103L
1694 /**
1695 * @brief Insert range from another %list.
1696 * @param __position Const_iterator referencing the element to
1697 * insert before.
1698 * @param __x Source list.
1699 * @param __first Const_iterator referencing the start of range in x.
1700 * @param __last Const_iterator referencing the end of range in x.
1701 *
1702 * Removes elements in the range [__first,__last) and inserts them
1703 * before @a __position in constant time.
1704 *
1705 * Undefined if @a __position is in [__first,__last).
1706 */
1707 void
1708 splice(const_iterator __position, list&& __x, const_iterator __first,
1709 const_iterator __last) noexcept
1710#else
1711 /**
1712 * @brief Insert range from another %list.
1713 * @param __position Iterator referencing the element to insert before.
1714 * @param __x Source list.
1715 * @param __first Iterator referencing the start of range in x.
1716 * @param __last Iterator referencing the end of range in x.
1717 *
1718 * Removes elements in the range [__first,__last) and inserts them
1719 * before @a __position in constant time.
1720 *
1721 * Undefined if @a __position is in [__first,__last).
1722 */
1723 void
1724 splice(iterator __position, list& __x, iterator __first,
1725 iterator __last)
1726#endif
1727 {
1728 if (__first != __last)
1729 {
1730 if (this != std::__addressof(__x))
1731 _M_check_equal_allocators(__x);
1732
1733 size_t __n = _S_distance(__first, __last);
1734 this->_M_inc_size(__n);
1735 __x._M_dec_size(__n);
1736
1737 this->_M_transfer(__position._M_const_cast(),
1738 __first._M_const_cast(),
1739 __last._M_const_cast());
1740 }
1741 }
1742
1743#if __cplusplus201703L >= 201103L
1744 /**
1745 * @brief Insert range from another %list.
1746 * @param __position Const_iterator referencing the element to
1747 * insert before.
1748 * @param __x Source list.
1749 * @param __first Const_iterator referencing the start of range in x.
1750 * @param __last Const_iterator referencing the end of range in x.
1751 *
1752 * Removes elements in the range [__first,__last) and inserts them
1753 * before @a __position in constant time.
1754 *
1755 * Undefined if @a __position is in [__first,__last).
1756 */
1757 void
1758 splice(const_iterator __position, list& __x, const_iterator __first,
1759 const_iterator __last) noexcept
1760 { splice(__position, std::move(__x), __first, __last); }
1761#endif
1762
1763 private:
1764#ifdef __glibcxx_list_remove_return_type // C++ >= 20 && HOSTED
1765 typedef size_type __remove_return_type;
1766# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG \
1767 __attribute__((__abi_tag__("__cxx20")))
1768#else
1769 typedef void __remove_return_type;
1770# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
1771#endif
1772 public:
1773
1774 /**
1775 * @brief Remove all elements equal to value.
1776 * @param __value The value to remove.
1777 *
1778 * Removes every element in the list equal to @a value.
1779 * Remaining elements stay in list order. Note that this
1780 * function only erases the elements, and that if the elements
1781 * themselves are pointers, the pointed-to memory is not
1782 * touched in any way. Managing the pointer is the user's
1783 * responsibility.
1784 */
1785 _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
1786 __remove_return_type
1787 remove(const _Tp& __value);
1788
1789 /**
1790 * @brief Remove all elements satisfying a predicate.
1791 * @tparam _Predicate Unary predicate function or object.
1792 *
1793 * Removes every element in the list for which the predicate
1794 * returns true. Remaining elements stay in list order. Note
1795 * that this function only erases the elements, and that if the
1796 * elements themselves are pointers, the pointed-to memory is
1797 * not touched in any way. Managing the pointer is the user's
1798 * responsibility.
1799 */
1800 template<typename _Predicate>
1801 __remove_return_type
1802 remove_if(_Predicate);
1803
1804 /**
1805 * @brief Remove consecutive duplicate elements.
1806 *
1807 * For each consecutive set of elements with the same value,
1808 * remove all but the first one. Remaining elements stay in
1809 * list order. Note that this function only erases the
1810 * elements, and that if the elements themselves are pointers,
1811 * the pointed-to memory is not touched in any way. Managing
1812 * the pointer is the user's responsibility.
1813 */
1814 _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
1815 __remove_return_type
1816 unique();
1817
1818 /**
1819 * @brief Remove consecutive elements satisfying a predicate.
1820 * @tparam _BinaryPredicate Binary predicate function or object.
1821 *
1822 * For each consecutive set of elements [first,last) that
1823 * satisfy predicate(first,i) where i is an iterator in
1824 * [first,last), remove all but the first one. Remaining
1825 * elements stay in list order. Note that this function only
1826 * erases the elements, and that if the elements themselves are
1827 * pointers, the pointed-to memory is not touched in any way.
1828 * Managing the pointer is the user's responsibility.
1829 */
1830 template<typename _BinaryPredicate>
1831 __remove_return_type
1832 unique(_BinaryPredicate);
1833
1834#undef _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG
1835
1836 /**
1837 * @brief Merge sorted lists.
1838 * @param __x Sorted list to merge.
1839 *
1840 * Assumes that both @a __x and this list are sorted according to
1841 * operator<(). Merges elements of @a __x into this list in
1842 * sorted order, leaving @a __x empty when complete. Elements in
1843 * this list precede elements in @a __x that are equal.
1844 */
1845#if __cplusplus201703L >= 201103L
1846 void
1847 merge(list&& __x);
1848
1849 void
1850 merge(list& __x)
1851 { merge(std::move(__x)); }
1852#else
1853 void
1854 merge(list& __x);
1855#endif
1856
1857 /**
1858 * @brief Merge sorted lists according to comparison function.
1859 * @tparam _StrictWeakOrdering Comparison function defining
1860 * sort order.
1861 * @param __x Sorted list to merge.
1862 * @param __comp Comparison functor.
1863 *
1864 * Assumes that both @a __x and this list are sorted according to
1865 * StrictWeakOrdering. Merges elements of @a __x into this list
1866 * in sorted order, leaving @a __x empty when complete. Elements
1867 * in this list precede elements in @a __x that are equivalent
1868 * according to StrictWeakOrdering().
1869 */
1870#if __cplusplus201703L >= 201103L
1871 template<typename _StrictWeakOrdering>
1872 void
1873 merge(list&& __x, _StrictWeakOrdering __comp);
1874
1875 template<typename _StrictWeakOrdering>
1876 void
1877 merge(list& __x, _StrictWeakOrdering __comp)
1878 { merge(std::move(__x), __comp); }
1879#else
1880 template<typename _StrictWeakOrdering>
1881 void
1882 merge(list& __x, _StrictWeakOrdering __comp);
1883#endif
1884
1885 /**
1886 * @brief Reverse the elements in list.
1887 *
1888 * Reverse the order of elements in the list in linear time.
1889 */
1890 void
1891 reverse() _GLIBCXX_NOEXCEPTnoexcept
1892 { this->_M_impl._M_node._M_reverse(); }
1893
1894 /**
1895 * @brief Sort the elements.
1896 *
1897 * Sorts the elements of this list in NlogN time. Equivalent
1898 * elements remain in list order.
1899 */
1900 void
1901 sort();
1902
1903 /**
1904 * @brief Sort the elements according to comparison function.
1905 *
1906 * Sorts the elements of this list in NlogN time. Equivalent
1907 * elements remain in list order.
1908 */
1909 template<typename _StrictWeakOrdering>
1910 void
1911 sort(_StrictWeakOrdering);
1912
1913 protected:
1914 // Internal constructor functions follow.
1915
1916 // Called by the range constructor to implement [23.1.1]/9
1917
1918 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1919 // 438. Ambiguity in the "do the right thing" clause
1920 template<typename _Integer>
1921 void
1922 _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type)
1923 { _M_fill_initialize(static_cast<size_type>(__n), __x); }
1924
1925 // Called by the range constructor to implement [23.1.1]/9
1926 template<typename _InputIterator>
1927 void
1928 _M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
1929 __false_type)
1930 {
1931 for (; __first != __last; ++__first)
1932#if __cplusplus201703L >= 201103L
1933 emplace_back(*__first);
1934#else
1935 push_back(*__first);
1936#endif
1937 }
1938
1939 // Called by list(n,v,a), and the range constructor when it turns out
1940 // to be the same thing.
1941 void
1942 _M_fill_initialize(size_type __n, const value_type& __x)
1943 {
1944 for (; __n; --__n)
1945 push_back(__x);
1946 }
1947
1948#if __cplusplus201703L >= 201103L
1949 // Called by list(n).
1950 void
1951 _M_default_initialize(size_type __n)
1952 {
1953 for (; __n; --__n)
1954 emplace_back();
1955 }
1956
1957 // Called by resize(sz).
1958 void
1959 _M_default_append(size_type __n);
1960#endif
1961
1962 // Internal assign functions follow.
1963
1964 // Called by the range assign to implement [23.1.1]/9
1965
1966 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1967 // 438. Ambiguity in the "do the right thing" clause
1968 template<typename _Integer>
1969 void
1970 _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
1971 { _M_fill_assign(__n, __val); }
1972
1973 // Called by the range assign to implement [23.1.1]/9
1974 template<typename _InputIterator>
1975 void
1976 _M_assign_dispatch(_InputIterator __first, _InputIterator __last,
1977 __false_type);
1978
1979 // Called by assign(n,t), and the range assign when it turns out
1980 // to be the same thing.
1981 void
1982 _M_fill_assign(size_type __n, const value_type& __val);
1983
1984
1985 // Moves the elements from [first,last) before position.
1986 void
1987 _M_transfer(iterator __position, iterator __first, iterator __last)
1988 { __position._M_node->_M_transfer(__first._M_node, __last._M_node); }
1989
1990 // Inserts new element at position given and with value given.
1991#if __cplusplus201703L < 201103L
1992 void
1993 _M_insert(iterator __position, const value_type& __x)
1994 {
1995 _Node* __tmp = _M_create_node(__x);
1996 __tmp->_M_hook(__position._M_node);
1997 this->_M_inc_size(1);
1998 }
1999#else
2000 template<typename... _Args>
2001 void
2002 _M_insert(iterator __position, _Args&&... __args)
2003 {
2004 _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...);
2005 __tmp->_M_hook(__position._M_node);
2006 this->_M_inc_size(1);
2007 }
2008#endif
2009
2010 // Erases element at position given.
2011 void
2012 _M_erase(iterator __position) _GLIBCXX_NOEXCEPTnoexcept
2013 {
2014 this->_M_dec_size(1);
2015 __position._M_node->_M_unhook();
2016 _Node* __n = static_cast<_Node*>(__position._M_node);
2017#if __cplusplus201703L >= 201103L
2018 _Node_alloc_traits::destroy(_M_get_Node_allocator(), __n->_M_valptr());
2019#else
2020 _Tp_alloc_type(_M_get_Node_allocator()).destroy(__n->_M_valptr());
2021#endif
2022
2023 _M_put_node(__n);
2024 }
2025
2026 // To implement the splice (and merge) bits of N1599.
2027 void
2028 _M_check_equal_allocators(const list& __x) _GLIBCXX_NOEXCEPTnoexcept
2029 {
2030 if (_M_get_Node_allocator() != __x._M_get_Node_allocator())
2031 __builtin_abort();
2032 }
2033
2034 // Used to implement resize.
2035 const_iterator
2036 _M_resize_pos(size_type& __new_size) const;
2037
2038#if __cplusplus201703L >= 201103L
2039 void
2040 _M_move_assign(list&& __x, true_type) noexcept
2041 {
2042 this->clear();
2043 this->_M_move_nodes(std::move(__x));
2044 std::__alloc_on_move(this->_M_get_Node_allocator(),
2045 __x._M_get_Node_allocator());
2046 }
2047
2048 void
2049 _M_move_assign(list&& __x, false_type)
2050 {
2051 if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator())
2052 _M_move_assign(std::move(__x), true_type{});
2053 else
2054 // The rvalue's allocator cannot be moved, or is not equal,
2055 // so we need to individually move each element.
2056 _M_assign_dispatch(std::make_move_iterator(__x.begin()),
2057 std::make_move_iterator(__x.end()),
2058 __false_type{});
2059 }
2060#endif
2061
2062#if _GLIBCXX_USE_CXX11_ABI1
2063 // Update _M_size members after merging (some of) __src into __dest.
2064 struct _Finalize_merge
2065 {
2066 explicit
2067 _Finalize_merge(list& __dest, list& __src, const iterator& __src_next)
2068 : _M_dest(__dest), _M_src(__src), _M_next(__src_next)
2069 { }
2070
2071 ~_Finalize_merge()
2072 {
2073 // For the common case, _M_next == _M_sec.end() and the std::distance
2074 // call is fast. But if any *iter1 < *iter2 comparison throws then we
2075 // have to count how many elements remain in _M_src.
2076 const size_t __num_unmerged = std::distance(_M_next, _M_src.end());
2077 const size_t __orig_size = _M_src._M_get_size();
2078 _M_dest._M_inc_size(__orig_size - __num_unmerged);
2079 _M_src._M_set_size(__num_unmerged);
2080 }
2081
2082 list& _M_dest;
2083 list& _M_src;
2084 const iterator& _M_next;
2085
2086#if __cplusplus201703L >= 201103L
2087 _Finalize_merge(const _Finalize_merge&) = delete;
2088#endif
2089 };
2090#else
2091 struct _Finalize_merge
2092 { explicit _Finalize_merge(list&, list&, const iterator&) { } };
2093#endif
2094
2095 };
2096
2097#if __cpp_deduction_guides201703L >= 201606
2098 template<typename _InputIterator, typename _ValT
2099 = typename iterator_traits<_InputIterator>::value_type,
2100 typename _Allocator = allocator<_ValT>,
2101 typename = _RequireInputIter<_InputIterator>,
2102 typename = _RequireAllocator<_Allocator>>
2103 list(_InputIterator, _InputIterator, _Allocator = _Allocator())
2104 -> list<_ValT, _Allocator>;
2105#endif
2106
2107_GLIBCXX_END_NAMESPACE_CXX11}
2108
2109 /**
2110 * @brief List equality comparison.
2111 * @param __x A %list.
2112 * @param __y A %list of the same type as @a __x.
2113 * @return True iff the size and elements of the lists are equal.
2114 *
2115 * This is an equivalence relation. It is linear in the size of
2116 * the lists. Lists are considered equivalent if their sizes are
2117 * equal, and if corresponding elements compare equal.
2118 */
2119 template<typename _Tp, typename _Alloc>
2120 _GLIBCXX_NODISCARD[[__nodiscard__]]
2121 inline bool
2122 operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2123 {
2124#if _GLIBCXX_USE_CXX11_ABI1
2125 if (__x.size() != __y.size())
2126 return false;
2127#endif
2128
2129 typedef typename list<_Tp, _Alloc>::const_iterator const_iterator;
2130 const_iterator __end1 = __x.end();
2131 const_iterator __end2 = __y.end();
2132
2133 const_iterator __i1 = __x.begin();
2134 const_iterator __i2 = __y.begin();
2135 while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2)
2136 {
2137 ++__i1;
2138 ++__i2;
2139 }
2140 return __i1 == __end1 && __i2 == __end2;
2141 }
2142
2143#if __cpp_lib_three_way_comparison
2144/**
2145 * @brief List ordering relation.
2146 * @param __x A `list`.
2147 * @param __y A `list` of the same type as `__x`.
2148 * @return A value indicating whether `__x` is less than, equal to,
2149 * greater than, or incomparable with `__y`.
2150 *
2151 * See `std::lexicographical_compare_three_way()` for how the determination
2152 * is made. This operator is used to synthesize relational operators like
2153 * `<` and `>=` etc.
2154 */
2155 template<typename _Tp, typename _Alloc>
2156 [[nodiscard]]
2157 inline __detail::__synth3way_t<_Tp>
2158 operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2159 {
2160 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
2161 __y.begin(), __y.end(),
2162 __detail::__synth3way);
2163 }
2164#else
2165 /**
2166 * @brief List ordering relation.
2167 * @param __x A %list.
2168 * @param __y A %list of the same type as @a __x.
2169 * @return True iff @a __x is lexicographically less than @a __y.
2170 *
2171 * This is a total ordering relation. It is linear in the size of the
2172 * lists. The elements must be comparable with @c <.
2173 *
2174 * See std::lexicographical_compare() for how the determination is made.
2175 */
2176 template<typename _Tp, typename _Alloc>
2177 _GLIBCXX_NODISCARD[[__nodiscard__]]
2178 inline bool
2179 operator<(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2180 { return std::lexicographical_compare(__x.begin(), __x.end(),
2181 __y.begin(), __y.end()); }
2182
2183 /// Based on operator==
2184 template<typename _Tp, typename _Alloc>
2185 _GLIBCXX_NODISCARD[[__nodiscard__]]
2186 inline bool
2187 operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2188 { return !(__x == __y); }
2189
2190 /// Based on operator<
2191 template<typename _Tp, typename _Alloc>
2192 _GLIBCXX_NODISCARD[[__nodiscard__]]
2193 inline bool
2194 operator>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2195 { return __y < __x; }
2196
2197 /// Based on operator<
2198 template<typename _Tp, typename _Alloc>
2199 _GLIBCXX_NODISCARD[[__nodiscard__]]
2200 inline bool
2201 operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2202 { return !(__y < __x); }
2203
2204 /// Based on operator<
2205 template<typename _Tp, typename _Alloc>
2206 _GLIBCXX_NODISCARD[[__nodiscard__]]
2207 inline bool
2208 operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
2209 { return !(__x < __y); }
2210#endif // three-way comparison
2211
2212 /// See std::list::swap().
2213 template<typename _Tp, typename _Alloc>
2214 inline void
2215 swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
2216 _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))noexcept(noexcept(__x.swap(__y)))
2217 { __x.swap(__y); }
2218
2219_GLIBCXX_END_NAMESPACE_CONTAINER
2220
2221#if _GLIBCXX_USE_CXX11_ABI1
2222
2223 // Detect when distance is used to compute the size of the whole list.
2224 template<typename _Tp>
2225 inline ptrdiff_t
2226 __distance(_GLIBCXX_STD_Cstd::_List_iterator<_Tp> __first,
2227 _GLIBCXX_STD_Cstd::_List_iterator<_Tp> __last,
2228 input_iterator_tag __tag)
2229 {
2230 typedef _GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> _CIter;
2231 return std::__distance(_CIter(__first), _CIter(__last), __tag);
2232 }
2233
2234 template<typename _Tp>
2235 inline ptrdiff_t
2236 __distance(_GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> __first,
2237 _GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> __last,
2238 input_iterator_tag)
2239 {
2240 typedef __detail::_List_node_header _Sentinel;
2241 _GLIBCXX_STD_Cstd::_List_const_iterator<_Tp> __beyond = __last;
2242 ++__beyond;
2243 const bool __whole = __first == __beyond;
2244 if (__builtin_constant_p (__whole) && __whole)
2245 return static_cast<const _Sentinel*>(__last._M_node)->_M_size;
2246
2247 ptrdiff_t __n = 0;
2248 while (__first != __last)
2249 {
2250 ++__first;
2251 ++__n;
2252 }
2253 return __n;
2254 }
2255#endif
2256
2257_GLIBCXX_END_NAMESPACE_VERSION
2258} // namespace std
2259
2260#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_font_combobox_view.h"
38#include "lc_property_qstring_list_combobox_view.h"
39#include "lc_property_rsvector.h"
40#include "lc_propertyprovider_utils.h"
41#include "lc_propertysheetwidget.h"
42#include "rs.h"
43#include "rs_entity.h"
44
45class LC_EnumDescriptor;
46class LC_PropertySheetWidget;
47class LC_ActionContext;
48class RS_Document;
49
50class LC_EntityTypePropertiesProvider : public LC_PropertyContainerBuilder {
51 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:
52 using FunCreateGenericProperty = typename std::function<void(const LC_Property::Names& names, RS_Entity* entity,
53 LC_PropertyContainer* container, QList<LC_PropertyAtomic*>*)>;
54
55 LC_EntityTypePropertiesProvider(const RS2::EntityType entityType, LC_ActionContext* actionContext, LC_PropertySheetWidget* widget)
56 : LC_PropertyContainerBuilder(actionContext,widget), m_entityType{entityType} {
57 }
58
59 static const QString SECTION_GENERAL;
60 static const QString SECTION_GEOMETRY;
61 static const QString SECTION_CALCULATED_INFO;
62 static const QString SECTION_SINGLE_ENTITY_ACTIONS;
63 static const QString SECTION_MULTI_ENTITY_ACTIONS;
64 static const QString SECTION_TEXT;
65 static const QString SECTION_TOOL_OPTIONS;
66 static const QString SECTION_SNAP_TOOL_OPTIONS;
67
68 void fillEntityProperties(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
69protected:
70
71 RS2::EntityType m_entityType;
72
73 virtual void fillSelectedSetCommands(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
74 virtual void fillComputedProperites(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
75 virtual void fillSingleEntityCommands(LC_PropertyContainer* container, const QList<RS_Entity*>& entitiesList);
76
77 virtual void doCreateCalculatedProperties([[maybe_unused]]LC_PropertyContainer* container, [[maybe_unused]]const QList<RS_Entity*>& list) {}
78 virtual void doCreateSingleEntityCommands(LC_PropertyContainer* cont, RS_Entity* entity);
79 virtual void doCreateEntitySpecificProperties(LC_PropertyContainer* container, const QList<RS_Entity*>& list) = 0;
80 virtual void doCreateSelectedSetCommands(LC_PropertyContainer* propertyContainer, const QList<RS_Entity*>& list);
81
82
83 bool isShowLinks() const {
84 return m_widget->getOptions()->showLinks;
85 }
86
87 bool isShowSingleEntitySection() const {
88 return m_widget->getOptions()->showSingleEntityCommands;
89 }
90
91 bool isShowComputedSection() const {
92 return m_widget->getOptions()->showComputed;
93 }
94
95 template <typename EntityType>
96 void add(const LC_Property::Names& names,
97 std::function<void(const LC_Property::Names& names, EntityType* entity, LC_PropertyContainer* container,
98 QList<LC_PropertyAtomic*>*)> propertyInit, const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
99
100 template <class ValueType, class EntityClass>
101 void createDelegatedStorage(typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueGet funGet,
102 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueSetShort funSet,
103 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueEqual funEqual,
104 EntityClass* entity, LC_PropertySingle<ValueType>* property);
105
106 template <class EntityClass>
107 void createEntityContextCommand(LC_PropertyContainer* container, const QString& propertyName, RS2::ActionType actionType,
108 const QString& linkTitle, const QString& linkTooltip, RS2::ActionType actionTypeRight,
109 const QString& linkTitleRight, const QString& linkTooltipRight, EntityClass* entity, const QString& commonDescription,
110 bool setContextEntity = true);
111
112
113
114 template <class EntityClass>
115 void createEntityContextCommands(const std::list<CommandLinkInfo>& links, LC_PropertyContainer* container, EntityClass* entity, const QString& namePrefix, bool setContextEntity = true);
116
117
118 template <class EntityClass>
119 void doCreateDelegatedVector(const LC_Property::Names& names,
120 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
121 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueSetShort funSet,
122 RS2::EntityType entityType, const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
123
124 void addCommon(const LC_Property::Names& names, const FunCreateGenericProperty& propertyInit, const QList<RS_Entity*>& list,
125 LC_PropertyContainer* cont);
126
127 void addMultipleProperties(LC_PropertyContainer* cont, QList<LC_PropertyAtomic*> props);
128
129 void fillGenericAttributes(LC_PropertyContainer* container, const QList<RS_Entity*>& list);
130
131 template <typename EntityClass>
132 void addVector(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
133 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
134 LC_PropertyContainer* cont) {
135 doCreateDelegatedVector<EntityClass>(names, funGet, funSet, m_entityType, list, cont);
136 }
137
138 template <typename EntityClass>
139 void addReadOnlyVector(const LC_Property::Names& names,
140 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
141 const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
142
143 template <typename EntityClass>
144 void addLinearDistance(const LC_Property::Names& names,
145 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
146 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
147 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
148 std::function<void(LC_PropertyViewDescriptor*)> funFillViewAttrs = nullptr);
149
150 template <typename EntityClass>
151 void addDouble(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
152 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
153 LC_PropertyContainer* cont, std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funFillViewAttrs = nullptr);
154
155 template <typename EntityClass>
156 void addWCSAngle(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
157 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
158 LC_PropertyContainer* cont);
159
160 template <typename EntityClass>
161 void addRawAngle(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
162 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
163 LC_PropertyContainer* cont);
164
165 template <typename EntityClass>
166 void addBoolean(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueGet funGet,
167 typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
168 LC_PropertyContainer* cont, const QString& viewName = LC_PropertyBoolCheckBoxView::VIEW_NAME,
169 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funPrepareDescriptor = nullptr);
170
171 template <typename EntityClass>
172 void addStringList(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
173 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
174 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funFillList,
175 // fixme - this may be expanded to support item icon, display name and data + change in View
176 const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
177
178 template <class EntityClass>
179 void addStringFont(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
180 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
181 const QList<RS_Entity*>& list, LC_PropertyContainer* cont);
182
183 template <class EntityClass>
184 void addString(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
185 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
186 LC_PropertyContainer* cont, bool multiLine,
187 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funPrepareDescriptor = nullptr);
188
189 template <typename EntityClass>
190 void addIntSpinbox(const LC_Property::Names& names, typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueGet funGet,
191 typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueSetShort funSet, const QList<RS_Entity*>& list,
192 LC_PropertyContainer* cont, int minVal = 1, int maxVal = -1);
193
194 template <typename EntityClass>
195 void addEnum(const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
196 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet funGetValue,
197 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
198 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
199 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> funPrepareDescriptor = nullptr);
200
201 template <typename EntityClass>
202 void addVarEnum(const LC_Property::Names& names, std::function<LC_EnumDescriptor*(EntityClass*)> funEnumDescriptorProvider,
203 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet funGetValue,
204 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
205 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
206 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funPrepareDescriptor = nullptr);
207
208 template <typename EntityClass>
209 void addReadOnlyString(const LC_Property::Names& names, std::function<QString(EntityClass*)> funValue, const QList<RS_Entity*>& list,
210 LC_PropertyContainer* cont);
211
212 LC_PropertyContainer* createGeometrySection(LC_PropertyContainer* container) const;
213 LC_PropertyContainer* createTextContainer(LC_PropertyContainer* container) const;
214 LC_PropertyContainer* createCalculatedInfoSection(LC_PropertyContainer* container) const;
215 LC_PropertyContainer* createSingleEntityActionsSection(LC_PropertyContainer* container) const;
216 LC_PropertyContainer* createMultipleEntityActionsSection(LC_PropertyContainer* container) const;
217};
218
219template <typename EntityType>
220void LC_EntityTypePropertiesProvider::add(const LC_Property::Names& names,
221 std::function<void(const LC_Property::Names& names, EntityType* entity,
222 LC_PropertyContainer* container, QList<LC_PropertyAtomic*>*)> propertyInit,
223 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
224 QList<LC_PropertyAtomic*> props;
225 props.reserve(list.size());
226 for (const auto entity : list) {
227 if (entity->rtti() != m_entityType) {
228 continue;
229 }
230 auto typedEntity = static_cast<EntityType*>(entity);
231 propertyInit(names, typedEntity, cont, &props);
232 }
233 addMultipleProperties(cont, props);
234}
235
236template <typename EntityClass>
237void LC_EntityTypePropertiesProvider::addLinearDistance(const LC_Property::Names& names,
238 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
239 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort
240 funSet, const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
241 std::function<void(LC_PropertyViewDescriptor*)> funFillViewAttrs) {
242 add<EntityClass>(names, [this, funGet, funSet,funFillViewAttrs](const LC_Property::Names& n, EntityClass* entity,
243 LC_PropertyContainer* container,
244 QList<LC_PropertyAtomic*>* props) -> void {
245 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::DISTANCE,
246 m_actionContext, m_widget);
247 if (funFillViewAttrs != nullptr) {
248 LC_PropertyViewDescriptor descriptor;
249 funFillViewAttrs(&descriptor);
250 property->setViewDescriptor(descriptor);
251 }
252
253 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
254 property->setValueStorage(valueStorage, true);
255 valueStorage->setup(entity, m_widget, funGet, funSet, [funGet](const double& v, EntityClass* e) -> bool {
256 return LC_LineMath::isSameLength(v, funGet(e));
257 });
258 }, list, cont);
259}
260
261template <typename EntityClass>
262void LC_EntityTypePropertiesProvider::addDouble(const LC_Property::Names& names,
263 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
264 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
265 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
266 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funFillViewAttrs) {
267 add<EntityClass>(names, [this, funGet, funSet,funFillViewAttrs](const LC_Property::Names& n, EntityClass* entity,
268 LC_PropertyContainer* container,
269 QList<LC_PropertyAtomic*>* props) -> void {
270 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::NOTNEEDED,
271 m_actionContext, m_widget);
272 bool readonly = false;
273 if (funFillViewAttrs != nullptr) {
274 LC_PropertyViewDescriptor descriptor;
275 readonly = funFillViewAttrs(entity, descriptor);
276 property->setViewDescriptor(descriptor);
277 }
278
279 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
280 property->setValueStorage(valueStorage, true);
281 valueStorage->setup(entity, m_widget, funGet, funSet, [funGet](const double& v, EntityClass* e) -> bool {
282 return LC_LineMath::isSameLength(v, funGet(e));
283 });
284 if (readonly || funSet == nullptr) {
285 property->setReadOnly();
286 }
287 }, list, cont);
288}
289
290template <typename EntityClass>
291void LC_EntityTypePropertiesProvider::addBoolean(const LC_Property::Names& names,
292 typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueGet funGet,
293 typename LC_EntityPropertyValueDelegate<bool, EntityClass>::FunValueSetShort funSet,
294 const QList<RS_Entity*>& list, LC_PropertyContainer* cont, const QString& viewName,
295 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)>
296 funPrepareDescriptor) {
297 add<EntityClass>(names, [this, funGet, funSet, viewName,funPrepareDescriptor](const LC_Property::Names& n, EntityClass* entity,
298 LC_PropertyContainer* container,
299 QList<LC_PropertyAtomic*>* props) -> void {
300 auto property = new LC_PropertyBool(container, false);
301 property->setNames(n);
302
303 LC_PropertyViewDescriptor descriptor(viewName.toLatin1());
304 bool readOnly = false;
305 if (funPrepareDescriptor != nullptr) {
306 readOnly = funPrepareDescriptor(entity, descriptor);
307 }
308 property->setViewDescriptor(descriptor);
309 props->push_back(property);
310 createDelegatedStorage<bool, EntityClass>(funGet, funSet, [funGet](bool& v, EntityClass* e) -> bool {
311 return v == funGet(e);
312 }, entity, property);
313 if (funSet == nullptr || readOnly) {
314 property->setReadOnly();
315 }
316 }, list, cont);
317}
318
319template <typename EntityClass>
320void LC_EntityTypePropertiesProvider::addReadOnlyString(const LC_Property::Names& names, std::function<QString(EntityClass*)> funValue,
321 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
322 add<EntityClass>(names, [this, funValue](const LC_Property::Names& n, EntityClass* e, LC_PropertyContainer* container,
323 QList<LC_PropertyAtomic*>* props) -> void {
324 const QString value = funValue(e);
325 createReadonlyStringProperty(n, props, container, value);
326 }, list, cont);
327}
328
329template <typename EntityClass>
330void LC_EntityTypePropertiesProvider::addStringList(const LC_Property::Names& names,
331 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
332 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
333 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funFillList,
334 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
335 add<EntityClass>(names, [this, funFillList, funGet, funSet](const LC_Property::Names& n, EntityClass* entity,
336 LC_PropertyContainer* container, QList<LC_PropertyAtomic*>* props) -> void {
337 auto property = new LC_PropertyQString(container, false);
338 property->setNames(n);
339 LC_PropertyViewDescriptor descriptor(LC_PropertyQStringListComboBoxView::VIEW_NAME);
340 bool readonly = funFillList(entity, descriptor);
341 property->setViewDescriptor(descriptor);
342 props->push_back(property);
343 createDelegatedStorage<QString, EntityClass>(funGet, funSet, [funGet](QString& v, EntityClass* e) -> bool {
344 return v == funGet(e);
345 }, entity, property);
346 if (readonly || funSet == nullptr) {
347 property->setReadOnly();
348 }
349 }, list, cont);
350}
351
352template <typename EntityClass>
353void LC_EntityTypePropertiesProvider::addStringFont(const LC_Property::Names& names,
354 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
355 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
356 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
357 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
358 QList<LC_PropertyAtomic*>* props) -> void {
359 auto property = new LC_PropertyQString(container, false);
360 property->setNames(n);
361 LC_PropertyViewDescriptor viewDescriptor;
362 viewDescriptor.viewName = LC_PropertyQStringFontComboboxView::VIEW_NAME;
363 property->setViewDescriptor(viewDescriptor);
364 props->push_back(property);
365
366 auto valueStorage = new LC_EntityPropertyValueDelegate<QString, EntityClass>();
367 property->setValueStorage(valueStorage, true);
368 valueStorage->setup(entity, this->m_widget, funGet, funSet, [funGet](QString& v, EntityClass* e) -> bool {
369 return v == funGet(e);
370 });
371 }, list, cont);
372}
373
374template <typename EntityClass>
375void LC_EntityTypePropertiesProvider::addString(const LC_Property::Names& names,
376 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueGet funGet,
377 typename LC_EntityPropertyValueDelegate<QString, EntityClass>::FunValueSetShort funSet,
378 const QList<RS_Entity*>& list, LC_PropertyContainer* cont, bool multiLine,
379 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funPrepareDescriptor) {
380 add<EntityClass>(names, [this, funGet, funSet, multiLine, funPrepareDescriptor](const LC_Property::Names& n, EntityClass* entity,
381 LC_PropertyContainer* container,
382 QList<LC_PropertyAtomic*>* props) -> void {
383 auto property = new LC_PropertyQString(container, false);
384 property->setNames(n);
385 LC_PropertyViewDescriptor viewDescriptor;
386 viewDescriptor.viewName = LC_PropertyQStringLineEditView::VIEW_NAME;
387 viewDescriptor.attributes[LC_PropertyQStringLineEditView::ATTR_MULTILINE_EDIT] = multiLine;
388 property->setViewDescriptor(viewDescriptor);
389 props->push_back(property);
390
391 auto valueStorage = new LC_EntityPropertyValueDelegate<QString, EntityClass>();
392 property->setValueStorage(valueStorage, true);
393 valueStorage->setup(entity, this->m_widget, funGet, funSet, [funGet](QString& v, EntityClass* e) -> bool {
394 return v == funGet(e);
395 });
396
397 bool readonly = false;
398 if (funPrepareDescriptor != nullptr) {
399 readonly = funPrepareDescriptor(entity, viewDescriptor);
400 }
401 if (readonly || funSet == nullptr) {
402 property->setReadOnly();
403 }
404 }, list, cont);
405}
406
407template <typename EntityClass>
408void LC_EntityTypePropertiesProvider::addWCSAngle(const LC_Property::Names& names,
409 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
410 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
411 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
412 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
413 QList<LC_PropertyAtomic*>* props) -> void {
414 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::ANGLE, m_actionContext,
415 m_widget);
416 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
417 valueStorage->setup(entity, m_widget, [this, funGet](EntityClass* e) -> double {
418 const double wcsAngle = funGet(e);
419 const double ucsAngle = toUCSBasisAngle(wcsAngle); // here we return in UCS for editing*/
420 return ucsAngle;
421 }, (funSet != nullptr)
422 ? [this, funSet](const double& value,
423 EntityClass* e) -> void {
424 // here we expect value in radians and in ucs
425 const double ucsBasisAngle = value;
426 double wcsAngle = toWCSAngle(ucsBasisAngle);
427 funSet(wcsAngle, e);
428 }
429 : funSet, [funGet](const double& v, EntityClass* e) -> bool {
430 return LC_LineMath::isSameAngle(v, funGet(e));
431 });
432 if (funSet == nullptr) {
433 property->setReadOnly();
434 }
435 property->setValueStorage(valueStorage, true);
436 }, list, cont);
437}
438
439template <typename EntityClass>
440void LC_EntityTypePropertiesProvider::addRawAngle(const LC_Property::Names& names,
441 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueGet funGet,
442 typename LC_EntityPropertyValueDelegate<double, EntityClass>::FunValueSetShort funSet,
443 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
444 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
445 QList<LC_PropertyAtomic*>* props) -> void {
446 auto property = createDoubleProperty(n, props, container, LC_ActionContext::InteractiveInputInfo::InputType::ANGLE, m_actionContext,
447 m_widget);
448 auto valueStorage = new LC_EntityPropertyValueDelegate<double, EntityClass>();
449 valueStorage->setup(entity, m_widget, funGet, funSet, [funGet](const double& v, EntityClass* e) -> bool {
450 return LC_LineMath::isSameAngle(v, funGet(e));
451 });
452 property->setValueStorage(valueStorage, true);
453 }, list, cont);
454}
455
456template <typename EntityClass>
457void LC_EntityTypePropertiesProvider::addReadOnlyVector(const LC_Property::Names& names,
458 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet funGet,
459 const QList<RS_Entity*>& list, LC_PropertyContainer* cont) {
460 add<EntityClass>(names, [this, funGet](const LC_Property::Names& n, EntityClass* e, LC_PropertyContainer* container,
461 QList<LC_PropertyAtomic*>* props) -> void {
462 auto property = createVectorProperty(n, props, container, m_actionContext, m_widget);
463 auto valueStorage = new LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>();
464 property->setValueStorage(valueStorage, true);
465 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueSetShort funSet = nullptr;
466 valueStorage->setup(e, m_widget, funGet, funSet, nullptr);
467 property->setReadOnly();
468 }, list, cont);
469}
470
471template <typename EntityClass>
472void LC_EntityTypePropertiesProvider::doCreateDelegatedVector(const LC_Property::Names& names,
473 typename LC_EntityPropertyValueDelegate<RS_Vector, EntityClass>::FunValueGet
474 funGet,
475 typename LC_EntityPropertyValueDelegate<
476 RS_Vector, EntityClass>::FunValueSetShort funSet,
477 [[maybe_unused]] RS2::EntityType entityType, const QList<RS_Entity*>& list,
478 LC_PropertyContainer* cont) {
479 add<EntityClass>(names, [this, funGet, funSet](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
480 QList<LC_PropertyAtomic*>* props) -> void {
481 auto property = createVectorProperty(n, props, container, m_actionContext, m_widget);
482 createDelegatedStorage([this, funGet](EntityClass* e) -> RS_Vector {
483 const RS_Vector wcsVector = funGet(e);
484 const RS_Vector ucsVector = toUCS(wcsVector); // here we return in UCS for editing
485 return ucsVector;
486 }, (funSet != nullptr)
487 ? [this, funSet](const RS_Vector& userUCS, EntityClass* e) -> void {
488 RS_Vector ucsVector = toWCS(userUCS);
489 funSet(ucsVector, e);
490 }
491 : funSet, [this, funGet](RS_Vector& userUCS, EntityClass* e) -> bool {
492 auto originalWCS = funGet(e);
493 auto originalUCS = toUCS(originalWCS);
494 return userUCS == originalUCS;
495 }, entity, property);
496 if (funSet == nullptr) {
497 property->setReadOnly();
498 }
499 }, list, cont);
500}
501
502template <typename EntityClass>
503void LC_EntityTypePropertiesProvider::addEnum(const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
504 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet
505 funGetValue,
506 typename LC_EntityPropertyValueDelegate<
507 LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
508 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
509 std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)>
510 funPrepareDescriptor) {
511 add<EntityClass>(names, [this, funGetValue, funSetValue, funPrepareDescriptor, enumDescriptor](
512 const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
513 QList<LC_PropertyAtomic*>* props) -> void {
514 auto property = new LC_PropertyEnum(container, false);
515 property->setNames(n);
516 property->setEnumInfo(enumDescriptor);
517 props->push_back(property);
518 auto valueStorage = new LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>();
519 property->setValueStorage(valueStorage, true);
520 valueStorage->setup(entity, this->m_widget, funGetValue, funSetValue,
521 [funGetValue](LC_PropertyEnumValueType& v, EntityClass* e) -> bool {
522 return v == funGetValue(e);
523 });
524
525 bool readonly = false;
526 if (funPrepareDescriptor != nullptr) {
527 LC_PropertyViewDescriptor descriptor;
528 readonly = funPrepareDescriptor(entity, descriptor);
529 property->setViewDescriptor(descriptor);
530 }
531 if (readonly || funSetValue == nullptr) {
532 property->setReadOnly();
533 }
534 }, list, cont);
535}
536
537template <typename EntityClass>
538void LC_EntityTypePropertiesProvider::addVarEnum(const LC_Property::Names& names,
539 std::function<LC_EnumDescriptor*(EntityClass*)> funEnumDescriptorProvider,
540 typename LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>::FunValueGet
541 funGetValue,
542 typename LC_EntityPropertyValueDelegate<
543 LC_PropertyEnumValueType, EntityClass>::FunValueSetShort funSetValue,
544 const QList<RS_Entity*>& list, LC_PropertyContainer* cont,
545 std::function<bool(EntityClass*, LC_PropertyViewDescriptor&)> funPrepareDescriptor) {
546 add<EntityClass>(names, [this, funGetValue, funSetValue, funEnumDescriptorProvider, funPrepareDescriptor](
547 const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
548 QList<LC_PropertyAtomic*>* props) -> void {
549 auto property = new LC_PropertyEnum(container, false);
550 property->setNames(n);
551 auto enumInfo = funEnumDescriptorProvider(entity);
552 property->setEnumInfo(enumInfo);
553 props->push_back(property);
554
555 auto valueStorage = new LC_EntityPropertyValueDelegate<LC_PropertyEnumValueType, EntityClass>();
556 property->setValueStorage(valueStorage, true);
557 valueStorage->setup(entity, this->m_widget, funGetValue, funSetValue,
558 [funGetValue](LC_PropertyEnumValueType& v, EntityClass* e) -> bool {
559 return v == funGetValue(e);
560 });
561
562 bool readonly = false;
563 if (funPrepareDescriptor != nullptr) {
564 LC_PropertyViewDescriptor descriptor;
565 readonly = funPrepareDescriptor(entity, descriptor);
566 property->setViewDescriptor(descriptor);
567 }
568 if (readonly || funSetValue == nullptr) {
569 property->setReadOnly();
570 }
571 }, list, cont);
572}
573
574template <typename EntityClass>
575void LC_EntityTypePropertiesProvider::addIntSpinbox(const LC_Property::Names& names,
576 typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueGet funGet,
577 typename LC_EntityPropertyValueDelegate<int, EntityClass>::FunValueSetShort funSet,
578 const QList<RS_Entity*>& list, LC_PropertyContainer* cont, int minVal, int maxVal) {
579 add<EntityClass>(names, [this, funGet, funSet,minVal, maxVal](const LC_Property::Names& n, EntityClass* entity, LC_PropertyContainer* container,
580 QList<LC_PropertyAtomic*>* props) -> void {
581 auto* property = new LC_PropertyInt(container, false);
582 property->setNames(n);
583 props->push_back(property);
584
585 LC_PropertyViewDescriptor descriptor(LC_PropertyIntSpinBoxView::VIEW_NAME);
586 descriptor.attributes[LC_PropertyIntSpinBoxView::ATTR_MIN] = 1;
587 descriptor.attributes[LC_PropertyIntSpinBoxView::ATTR_STEP] = minVal;
588 if (maxVal > 0) {
589 descriptor.attributes[LC_PropertyIntSpinBoxView::ATTR_MAX] = maxVal;
590 }
591 property->setViewDescriptor(descriptor);
592
593 auto valueStorage = new LC_EntityPropertyValueDelegate<int, EntityClass>();
594 valueStorage->setup(entity, m_widget, funGet, funSet, [this, funGet](int& v, EntityClass* e) -> bool {
595 return v == funGet(e);
596 });
597 property->setValueStorage(valueStorage, true);
598 }, list, cont);
599}
600
601template <typename ValueType, typename EntityClass>
602void LC_EntityTypePropertiesProvider::createDelegatedStorage(
603 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueGet funGet,
604 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueSetShort funSet,
605 typename LC_EntityPropertyValueDelegate<ValueType, EntityClass>::FunValueEqual funEqual, EntityClass* entity,
606 LC_PropertySingle<ValueType>* property) {
607 auto valueStorage = new LC_EntityPropertyValueDelegate<ValueType, EntityClass>();
608 valueStorage->setup(entity, this->m_widget, funGet, funSet, funEqual);
609 property->setValueStorage(valueStorage, true);
610}
611
612template <typename EntityClass>
613void LC_EntityTypePropertiesProvider::createEntityContextCommand(LC_PropertyContainer* container, const QString& propertyName, RS2::ActionType actionType, const QString& linkTitle,
614 const QString& linkTooltip, RS2::ActionType actionTypeRight, const QString& linkTitleRight,
615 const QString& linkTooltipRight, EntityClass* entity,
616 const QString &commonDescription, bool setContextEntity) {
617 auto clickHandler = [this, actionType, actionTypeRight, setContextEntity]([[maybe_unused]] EntityClass* ent, const int linkIndex) {
618 switch (linkIndex) {
619 case 0: {
620 if (setContextEntity) {
621 m_actionContext->saveContextMenuActionContext(ent, ent->getMiddlePoint(), false);
622 }
623 m_actionContext->setCurrentAction(actionType, nullptr);
624 break;
625 }
626 case 1: {
627 if (setContextEntity) {
628 m_actionContext->saveContextMenuActionContext(ent, ent->getMiddlePoint(), false);
629 }
630 m_actionContext->setCurrentAction(actionTypeRight, nullptr);
631 break;
632 }
633 default:
634 break;
635 }
636 };
637 LC_PropertyProviderUtils::createSingleEntityCommand<EntityClass>(container, propertyName, linkTitle,
3
Calling 'createSingleEntityCommand<RS_Line>'
638 linkTooltip, linkTitleRight,
639 linkTooltipRight, entity,
640 clickHandler, commonDescription);
641}
642
643template <typename EntityClass>
644void LC_EntityTypePropertiesProvider::createEntityContextCommands(const std::list<CommandLinkInfo>& links, LC_PropertyContainer* container, EntityClass* entity, const QString &namePrefix,
645 bool setContextEntity) {
646 int idx = 0;
647 for (const auto &i: links) {
648 QString propertyName = QString("%1_%2").arg(namePrefix).arg(idx);
649 createEntityContextCommand(container, propertyName, i.leftLink.actionType, i.leftLink.title, i.leftLink.tooltip,
2
Calling 'LC_EntityTypePropertiesProvider::createEntityContextCommand'
650 i.rightLink.actionType, i.rightLink.title, i.rightLink.tooltip, entity, i.description, setContextEntity);
651 idx++;
652 }
653}
654
655#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 template <typename EntityClass>
103 void createDirectDelegatedBool(LC_PropertyContainer* container, const LC_Property::Names& names,
104 const typename LC_EntityPropertyValueDirectEntityDelegate<bool, EntityClass>::FunValueGet &funGet,
105 const std::function<void(const bool&, EntityClass*)> &funSet, EntityClass* entity) {
106 auto* property = new LC_PropertyBool(container, false);
107 property->setNames(names);
108 createDirectDelegatedStorage<bool, EntityClass>(funGet, funSet, entity, property);
109 property->setReadOnly(funSet == nullptr);
110 container->addChildProperty(property);
111 }
112
113 template <typename EntityClass>
114 void createDirectDelegatedDouble(LC_PropertyContainer* container, const LC_Property::Names& names,
115 const typename LC_EntityPropertyValueDirectEntityDelegate<double, EntityClass>::FunValueGet &funGet,
116 const std::function<void(const double&, EntityClass*)> &funSet, EntityClass* entity,
117 LC_ActionContext::InteractiveInputInfo::InputType inputType,
118 LC_ActionContext* actionContext, LC_LateCompletionRequestor* requestor) {
119 auto* property = new LC_PropertyDouble(container, false);
120 property->setNames(names);
121 property->setInteractiveInputType(inputType);
122 LC_PropertyViewDescriptor attrs;
123 attrs.viewName = LC_PropertyDoubleInteractivePickView::VIEW_NAME;
124 property->setViewDescriptor(attrs);
125 property->setActionContextAndLaterRequestor(actionContext, requestor);
126 createDirectDelegatedStorage<double, RS_Graphic>(funGet, funSet, entity, property);
127 property->setReadOnly(funSet == nullptr);
128 container->addChildProperty(property);
129 }
130
131 inline void createDirectDelegatedReadonlyString(LC_PropertyContainer* container, const LC_Property::Names& names, const QString& value) {
132 const auto gridTypeProperty = new LC_PropertyQString(container, true);
133 gridTypeProperty->setNames(names);
134 gridTypeProperty->setValue(value);
135 gridTypeProperty->setReadOnly(true);
136 container->addChildProperty(gridTypeProperty);
137 }
138
139 template <typename ValueType, typename EntityClass>
140 auto addDirectEnumWithDescriptor(LC_PropertyContainer* container, const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
141 const typename LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>::FunValueGet &funGetValue,
142 const typename LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>::FunValueSet &funSetValue,
143 EntityClass* entity, std::function<bool(EntityClass*, LC_PropertyViewDescriptor& descriptor)> &funPrepareDescriptor,
144 bool ownDescriptor = false) -> void {
145 auto property = new LC_PropertyEnum(container, false);
146 property->setNames(names);
147 property->setEnumInfo(enumDescriptor, ownDescriptor);
148 auto valueStorage = new LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>();
149 valueStorage->setup(entity, funGetValue, funSetValue);
150 property->setValueStorage(valueStorage, true);
151
152 bool readonly = false;
153 if (funPrepareDescriptor != nullptr) {
154 LC_PropertyViewDescriptor descriptor;
155 readonly = funPrepareDescriptor(entity, descriptor);
156 property->setViewDescriptor(descriptor);
157 }
158 if (readonly || funSetValue == nullptr) {
159 property->setReadOnly();
160 }
161 container->addChildProperty(property);
162 }
163
164 template <typename ValueType, typename EntityClass>
165 auto addDirectEnum(LC_PropertyContainer* container, const LC_Property::Names& names, const LC_EnumDescriptor* enumDescriptor,
166 const typename LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>::FunValueGet &funGet,
167 const std::function<void(const ValueType&, EntityClass*)> &funSet,
168 EntityClass* entity, const bool ownDescriptor = false) -> void {
169 auto property = new LC_PropertyEnum(container, false);
170 property->setNames(names);
171 property->setEnumInfo(enumDescriptor, ownDescriptor);
172 auto valueStorage = new LC_EntityPropertyValueDirectEntityDelegate<ValueType, EntityClass>();
173 auto funSetWrapped = [funSet](const ValueType& v, [[maybe_unused]] LC_PropertyChangeReason reason, EntityClass* e) -> void {
174 funSet(v, e);
175 };
176 valueStorage->setup(entity, funGet, funSetWrapped);
177 property->setValueStorage(valueStorage, true);
178 if (funSet == nullptr) {
179 property->setReadOnly();
180 }
181 container->addChildProperty(property);
182 }
183
184 template <typename EntityClass>
185 void createSingleEntityCommand(LC_PropertyContainer* container, const QString& propertyName, const QString& linkTitle,
186 const QString& linkTooltip, const QString& linkTitleRight,
187 const QString& linkTooltipRight, EntityClass* entity,
188 const std::function<void(EntityClass*, int linkIndex)> &clickHandler, const QString &commonDescription) {
189 auto* property = new LC_PropertyAction(container, true);
190 property->setName(propertyName);
191 property->setDisplayName("");
192 LC_PropertyViewDescriptor viewDescriptor("Link");
193 viewDescriptor[LC_PropertyActionLinkView::ATTR_TITLE] = linkTitle;
194 viewDescriptor[LC_PropertyActionLinkView::ATTR_TOOLTIP_LEFT] = linkTooltip;
195 if (!linkTitleRight.isEmpty()) {
4
Assuming the condition is false
5
Taking false branch
196 viewDescriptor[LC_PropertyActionLinkView::ATTR_TITLE_RIGHT] = linkTitleRight;
197 viewDescriptor[LC_PropertyActionLinkView::ATTR_TOOLTIP_RIGHT] = linkTooltipRight;
198 }
199 property->setEntity(entity);
200 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
201 QTimer::singleShot(10, [entity, linkIndex, clickHandler] { clickHandler(entity, linkIndex); });
202 };
203 property->setClickHandler(wrappingClickHandler);
204 property->setDescription(commonDescription);
205 property->setViewDescriptor(viewDescriptor);
206 container->addChildProperty(property);
207 }
208}
209
210#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
29// fixme - sand - no copy assignment operator!
30struct LC_PropertyViewDescriptor {
31 QByteArray viewName;
32 using Attributes = QMap<QByteArray, QVariant>;
33 Attributes attributes;
34
35 LC_PropertyViewDescriptor() = default;
36 LC_PropertyViewDescriptor(const LC_PropertyViewDescriptor& other);
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/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h

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