File: | home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx |
Warning: | line 259, column 43 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | ||||||
2 | /* | ||||||
3 | * This file is part of the LibreOffice project. | ||||||
4 | * | ||||||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | ||||||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
8 | * | ||||||
9 | * This file incorporates work covered by the following license notice: | ||||||
10 | * | ||||||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | ||||||
12 | * contributor license agreements. See the NOTICE file distributed | ||||||
13 | * with this work for additional information regarding copyright | ||||||
14 | * ownership. The ASF licenses this file to you under the Apache | ||||||
15 | * License, Version 2.0 (the "License"); you may not use this file | ||||||
16 | * except in compliance with the License. You may obtain a copy of | ||||||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | ||||||
18 | */ | ||||||
19 | |||||||
20 | #include <com/sun/star/drawing/FillStyle.hpp> | ||||||
21 | |||||||
22 | #include <svx/svdundo.hxx> | ||||||
23 | #include <svx/svdotext.hxx> | ||||||
24 | #include <svx/svdobj.hxx> | ||||||
25 | #include <svx/svdpage.hxx> | ||||||
26 | #include <svx/svdlayer.hxx> | ||||||
27 | #include <svx/svdmodel.hxx> | ||||||
28 | #include <svx/svdview.hxx> | ||||||
29 | #include <svx/xfillit0.hxx> | ||||||
30 | #include <svx/strings.hrc> | ||||||
31 | #include <svx/dialmgr.hxx> | ||||||
32 | #include <svx/scene3d.hxx> | ||||||
33 | #include <editeng/outlobj.hxx> | ||||||
34 | #include <svx/svdogrp.hxx> | ||||||
35 | #include <sdr/properties/itemsettools.hxx> | ||||||
36 | #include <svx/sdr/properties/properties.hxx> | ||||||
37 | #include <svx/svdocapt.hxx> | ||||||
38 | #include <svl/whiter.hxx> | ||||||
39 | #include <svx/e3dsceneupdater.hxx> | ||||||
40 | #include <svx/svdviter.hxx> | ||||||
41 | #include <svx/svdotable.hxx> // #i124389# | ||||||
42 | #include <vcl/svapp.hxx> | ||||||
43 | #include <sfx2/viewsh.hxx> | ||||||
44 | #include <svx/svdoashp.hxx> | ||||||
45 | |||||||
46 | |||||||
47 | // iterates over all views and unmarks this SdrObject if it is marked | ||||||
48 | static void ImplUnmarkObject( SdrObject* pObj ) | ||||||
49 | { | ||||||
50 | SdrViewIter aIter( pObj ); | ||||||
51 | for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() ) | ||||||
52 | { | ||||||
53 | pView->MarkObj( pObj, pView->GetSdrPageView(), true ); | ||||||
54 | } | ||||||
55 | } | ||||||
56 | |||||||
57 | SdrUndoAction::SdrUndoAction(SdrModel& rNewMod) | ||||||
58 | : rMod(rNewMod), m_nViewShellId(-1) | ||||||
59 | { | ||||||
60 | if (SfxViewShell* pViewShell = SfxViewShell::Current()) | ||||||
61 | m_nViewShellId = pViewShell->GetViewShellId(); | ||||||
62 | } | ||||||
63 | |||||||
64 | SdrUndoAction::~SdrUndoAction() {} | ||||||
65 | |||||||
66 | bool SdrUndoAction::CanRepeat(SfxRepeatTarget& rView) const | ||||||
67 | { | ||||||
68 | SdrView* pV=dynamic_cast<SdrView*>( &rView ); | ||||||
69 | if (pV!=nullptr) return CanSdrRepeat(*pV); | ||||||
70 | return false; | ||||||
71 | } | ||||||
72 | |||||||
73 | void SdrUndoAction::Repeat(SfxRepeatTarget& rView) | ||||||
74 | { | ||||||
75 | SdrView* pV=dynamic_cast<SdrView*>( &rView ); | ||||||
76 | if (pV!=nullptr) SdrRepeat(*pV); | ||||||
77 | DBG_ASSERT(pV!=nullptr,"Repeat: SfxRepeatTarget that was handed over is not a SdrView")do { if (true && (!(pV!=nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "77" ": "), "%s", "Repeat: SfxRepeatTarget that was handed over is not a SdrView" ); } } while (false); | ||||||
78 | } | ||||||
79 | |||||||
80 | OUString SdrUndoAction::GetRepeatComment(SfxRepeatTarget& rView) const | ||||||
81 | { | ||||||
82 | SdrView* pV=dynamic_cast<SdrView*>( &rView ); | ||||||
83 | if (pV!=nullptr) return GetSdrRepeatComment(); | ||||||
84 | return OUString(); | ||||||
85 | } | ||||||
86 | |||||||
87 | bool SdrUndoAction::CanSdrRepeat(SdrView& /*rView*/) const | ||||||
88 | { | ||||||
89 | return false; | ||||||
90 | } | ||||||
91 | |||||||
92 | void SdrUndoAction::SdrRepeat(SdrView& /*rView*/) | ||||||
93 | { | ||||||
94 | } | ||||||
95 | |||||||
96 | OUString SdrUndoAction::GetSdrRepeatComment() const | ||||||
97 | { | ||||||
98 | return OUString(); | ||||||
99 | } | ||||||
100 | |||||||
101 | ViewShellId SdrUndoAction::GetViewShellId() const | ||||||
102 | { | ||||||
103 | return m_nViewShellId; | ||||||
104 | } | ||||||
105 | |||||||
106 | SdrUndoGroup::SdrUndoGroup(SdrModel& rNewMod) | ||||||
107 | : SdrUndoAction(rNewMod), | ||||||
108 | eFunction(SdrRepeatFunc::NONE) | ||||||
109 | {} | ||||||
110 | |||||||
111 | SdrUndoGroup::~SdrUndoGroup() | ||||||
112 | { | ||||||
113 | } | ||||||
114 | |||||||
115 | void SdrUndoGroup::AddAction(std::unique_ptr<SdrUndoAction> pAct) | ||||||
116 | { | ||||||
117 | maActions.push_back(std::move(pAct)); | ||||||
118 | } | ||||||
119 | |||||||
120 | void SdrUndoGroup::Undo() | ||||||
121 | { | ||||||
122 | for (auto it = maActions.rbegin(); it != maActions.rend(); ++it) | ||||||
123 | (*it)->Undo(); | ||||||
124 | } | ||||||
125 | |||||||
126 | void SdrUndoGroup::Redo() | ||||||
127 | { | ||||||
128 | for (std::unique_ptr<SdrUndoAction> & pAction : maActions) | ||||||
129 | pAction->Redo(); | ||||||
130 | } | ||||||
131 | |||||||
132 | OUString SdrUndoGroup::GetComment() const | ||||||
133 | { | ||||||
134 | return aComment.replaceAll("%1", aObjDescription); | ||||||
135 | } | ||||||
136 | |||||||
137 | bool SdrUndoGroup::CanSdrRepeat(SdrView& rView) const | ||||||
138 | { | ||||||
139 | switch (eFunction) | ||||||
140 | { | ||||||
141 | case SdrRepeatFunc::NONE : return false; | ||||||
142 | case SdrRepeatFunc::Delete : return rView.AreObjectsMarked(); | ||||||
143 | case SdrRepeatFunc::CombinePolyPoly: return rView.IsCombinePossible(); | ||||||
144 | case SdrRepeatFunc::CombineOnePoly : return rView.IsCombinePossible(true); | ||||||
145 | case SdrRepeatFunc::DismantlePolys : return rView.IsDismantlePossible(); | ||||||
146 | case SdrRepeatFunc::DismantleLines : return rView.IsDismantlePossible(true); | ||||||
147 | case SdrRepeatFunc::ConvertToPoly : return rView.IsConvertToPolyObjPossible(); | ||||||
148 | case SdrRepeatFunc::ConvertToPath : return rView.IsConvertToPathObjPossible(); | ||||||
149 | case SdrRepeatFunc::Group : return rView.IsGroupPossible(); | ||||||
150 | case SdrRepeatFunc::Ungroup : return rView.IsUnGroupPossible(); | ||||||
151 | case SdrRepeatFunc::PutToTop : return rView.IsToTopPossible(); | ||||||
152 | case SdrRepeatFunc::PutToBottom : return rView.IsToBtmPossible(); | ||||||
153 | case SdrRepeatFunc::MoveToTop : return rView.IsToTopPossible(); | ||||||
154 | case SdrRepeatFunc::MoveToBottom : return rView.IsToBtmPossible(); | ||||||
155 | case SdrRepeatFunc::ReverseOrder : return rView.IsReverseOrderPossible(); | ||||||
156 | case SdrRepeatFunc::ImportMtf : return rView.IsImportMtfPossible(); | ||||||
157 | default: break; | ||||||
158 | } // switch | ||||||
159 | return false; | ||||||
160 | } | ||||||
161 | |||||||
162 | void SdrUndoGroup::SdrRepeat(SdrView& rView) | ||||||
163 | { | ||||||
164 | switch (eFunction) | ||||||
165 | { | ||||||
166 | case SdrRepeatFunc::NONE : break; | ||||||
167 | case SdrRepeatFunc::Delete : rView.DeleteMarked(); break; | ||||||
168 | case SdrRepeatFunc::CombinePolyPoly : rView.CombineMarkedObjects(false); break; | ||||||
169 | case SdrRepeatFunc::CombineOnePoly : rView.CombineMarkedObjects(); break; | ||||||
170 | case SdrRepeatFunc::DismantlePolys : rView.DismantleMarkedObjects(); break; | ||||||
171 | case SdrRepeatFunc::DismantleLines : rView.DismantleMarkedObjects(true); break; | ||||||
172 | case SdrRepeatFunc::ConvertToPoly : rView.ConvertMarkedToPolyObj(); break; | ||||||
173 | case SdrRepeatFunc::ConvertToPath : rView.ConvertMarkedToPathObj(false); break; | ||||||
174 | case SdrRepeatFunc::Group : rView.GroupMarked(); break; | ||||||
175 | case SdrRepeatFunc::Ungroup : rView.UnGroupMarked(); break; | ||||||
176 | case SdrRepeatFunc::PutToTop : rView.PutMarkedToTop(); break; | ||||||
177 | case SdrRepeatFunc::PutToBottom : rView.PutMarkedToBtm(); break; | ||||||
178 | case SdrRepeatFunc::MoveToTop : rView.MovMarkedToTop(); break; | ||||||
179 | case SdrRepeatFunc::MoveToBottom : rView.MovMarkedToBtm(); break; | ||||||
180 | case SdrRepeatFunc::ReverseOrder : rView.ReverseOrderOfMarked(); break; | ||||||
181 | case SdrRepeatFunc::ImportMtf : rView.DoImportMarkedMtf(); break; | ||||||
182 | default: break; | ||||||
183 | } // switch | ||||||
184 | } | ||||||
185 | |||||||
186 | OUString SdrUndoGroup::GetSdrRepeatComment() const | ||||||
187 | { | ||||||
188 | return aComment.replaceAll("%1", SvxResId(STR_ObjNameSingulPluralreinterpret_cast<char const *>("STR_ObjNameSingulPlural" "\004" u8"Draw object(s)"))); | ||||||
189 | } | ||||||
190 | |||||||
191 | SdrUndoObj::SdrUndoObj(SdrObject& rNewObj) | ||||||
192 | : SdrUndoAction(rNewObj.getSdrModelFromSdrObject()) | ||||||
193 | ,pObj(&rNewObj) | ||||||
194 | { | ||||||
195 | } | ||||||
196 | |||||||
197 | OUString SdrUndoObj::GetDescriptionStringForObject( const SdrObject& _rForObject, const char* pStrCacheID, bool bRepeat ) | ||||||
198 | { | ||||||
199 | const OUString rStr {SvxResId(pStrCacheID)}; | ||||||
200 | |||||||
201 | const sal_Int32 nPos = rStr.indexOf("%1"); | ||||||
202 | if (nPos < 0) | ||||||
203 | return rStr; | ||||||
204 | |||||||
205 | if (bRepeat) | ||||||
206 | return rStr.replaceAt(nPos, 2, SvxResId(STR_ObjNameSingulPluralreinterpret_cast<char const *>("STR_ObjNameSingulPlural" "\004" u8"Draw object(s)"))); | ||||||
207 | |||||||
208 | return rStr.replaceAt(nPos, 2, _rForObject.TakeObjNameSingul()); | ||||||
209 | } | ||||||
210 | |||||||
211 | OUString SdrUndoObj::ImpGetDescriptionStr(const char* pStrCacheID, bool bRepeat) const | ||||||
212 | { | ||||||
213 | if ( pObj ) | ||||||
214 | return GetDescriptionStringForObject( *pObj, pStrCacheID, bRepeat ); | ||||||
215 | return OUString(); | ||||||
216 | } | ||||||
217 | |||||||
218 | // common call method for possible change of the page when UNDO/REDO is triggered | ||||||
219 | void SdrUndoObj::ImpShowPageOfThisObject() | ||||||
220 | { | ||||||
221 | if(pObj && pObj->IsInserted() && pObj->getSdrPageFromSdrObject()) | ||||||
222 | { | ||||||
223 | SdrHint aHint(SdrHintKind::SwitchToPage, *pObj, pObj->getSdrPageFromSdrObject()); | ||||||
224 | pObj->getSdrModelFromSdrObject().Broadcast(aHint); | ||||||
225 | } | ||||||
226 | } | ||||||
227 | |||||||
228 | void SdrUndoAttrObj::ensureStyleSheetInStyleSheetPool(SfxStyleSheetBasePool& rStyleSheetPool, SfxStyleSheet& rSheet) | ||||||
229 | { | ||||||
230 | SfxStyleSheetBase* pThere = rStyleSheetPool.Find(rSheet.GetName(), rSheet.GetFamily()); | ||||||
231 | |||||||
232 | if(!pThere) | ||||||
233 | { | ||||||
234 | // re-insert remembered style which was removed in the meantime. To do this | ||||||
235 | // without assertion, do it without parent and set parent after insertion | ||||||
236 | const OUString aParent(rSheet.GetParent()); | ||||||
237 | |||||||
238 | rSheet.SetParent(OUString()); | ||||||
239 | rStyleSheetPool.Insert(&rSheet); | ||||||
240 | rSheet.SetParent(aParent); | ||||||
241 | } | ||||||
242 | } | ||||||
243 | |||||||
244 | SdrUndoAttrObj::SdrUndoAttrObj(SdrObject& rNewObj, bool bStyleSheet1, bool bSaveText) | ||||||
245 | : SdrUndoObj(rNewObj) | ||||||
246 | , mxUndoStyleSheet() | ||||||
247 | , mxRedoStyleSheet() | ||||||
248 | , bHaveToTakeRedoSet(true) | ||||||
249 | { | ||||||
250 | bStyleSheet = bStyleSheet1; | ||||||
251 | |||||||
252 | SdrObjList* pOL = rNewObj.GetSubList(); | ||||||
253 | bool bIsGroup(pOL!=nullptr && pOL->GetObjCount()); | ||||||
254 | bool bIs3DScene(bIsGroup && dynamic_cast< E3dScene* >(pObj) != nullptr); | ||||||
255 | |||||||
256 | if(bIsGroup
| ||||||
257 | { | ||||||
258 | // it's a group object! | ||||||
259 | pUndoGroup.reset(new SdrUndoGroup(pObj->getSdrModelFromSdrObject())); | ||||||
| |||||||
260 | const size_t nObjCount(pOL->GetObjCount()); | ||||||
261 | |||||||
262 | for(size_t nObjNum = 0; nObjNum < nObjCount; ++nObjNum) | ||||||
263 | { | ||||||
264 | pUndoGroup->AddAction( | ||||||
265 | std::make_unique<SdrUndoAttrObj>(*pOL->GetObj(nObjNum), bStyleSheet1)); | ||||||
266 | } | ||||||
267 | } | ||||||
268 | |||||||
269 | if(bIsGroup && !bIs3DScene) | ||||||
270 | return; | ||||||
271 | |||||||
272 | pUndoSet.reset( new SfxItemSet(pObj->GetMergedItemSet()) ); | ||||||
273 | |||||||
274 | if(bStyleSheet) | ||||||
275 | mxUndoStyleSheet = pObj->GetStyleSheet(); | ||||||
276 | |||||||
277 | if(bSaveText) | ||||||
278 | { | ||||||
279 | auto p = pObj->GetOutlinerParaObject(); | ||||||
280 | if(p) | ||||||
281 | pTextUndo.reset( new OutlinerParaObject(*p) ); | ||||||
282 | } | ||||||
283 | } | ||||||
284 | |||||||
285 | SdrUndoAttrObj::~SdrUndoAttrObj() | ||||||
286 | { | ||||||
287 | pUndoSet.reset(); | ||||||
288 | pRedoSet.reset(); | ||||||
289 | pUndoGroup.reset(); | ||||||
290 | pTextUndo.reset(); | ||||||
291 | pTextRedo.reset(); | ||||||
292 | } | ||||||
293 | |||||||
294 | void SdrUndoAttrObj::Undo() | ||||||
295 | { | ||||||
296 | E3DModifySceneSnapRectUpdater aUpdater(pObj); | ||||||
297 | bool bIs3DScene(dynamic_cast< E3dScene* >(pObj) != nullptr); | ||||||
298 | |||||||
299 | // Trigger PageChangeCall | ||||||
300 | ImpShowPageOfThisObject(); | ||||||
301 | |||||||
302 | if(!pUndoGroup || bIs3DScene) | ||||||
303 | { | ||||||
304 | if(bHaveToTakeRedoSet) | ||||||
305 | { | ||||||
306 | bHaveToTakeRedoSet = false; | ||||||
307 | |||||||
308 | pRedoSet.reset( new SfxItemSet(pObj->GetMergedItemSet()) ); | ||||||
309 | |||||||
310 | if(bStyleSheet) | ||||||
311 | mxRedoStyleSheet = pObj->GetStyleSheet(); | ||||||
312 | |||||||
313 | if(pTextUndo) | ||||||
314 | { | ||||||
315 | // #i8508# | ||||||
316 | auto p = pObj->GetOutlinerParaObject(); | ||||||
317 | if(p) | ||||||
318 | pTextRedo.reset( new OutlinerParaObject(*p) ); | ||||||
319 | } | ||||||
320 | } | ||||||
321 | |||||||
322 | if(bStyleSheet) | ||||||
323 | { | ||||||
324 | mxRedoStyleSheet = pObj->GetStyleSheet(); | ||||||
325 | SfxStyleSheet* pSheet = dynamic_cast< SfxStyleSheet* >(mxUndoStyleSheet.get()); | ||||||
326 | |||||||
327 | if(pSheet && pObj->getSdrModelFromSdrObject().GetStyleSheetPool()) | ||||||
328 | { | ||||||
329 | ensureStyleSheetInStyleSheetPool(*pObj->getSdrModelFromSdrObject().GetStyleSheetPool(), *pSheet); | ||||||
330 | pObj->SetStyleSheet(pSheet, true); | ||||||
331 | } | ||||||
332 | else | ||||||
333 | { | ||||||
334 | OSL_ENSURE(false, "OOps, something went wrong in SdrUndoAttrObj (!)")do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "334" ": "), "%s", "OOps, something went wrong in SdrUndoAttrObj (!)" ); } } while (false); | ||||||
335 | } | ||||||
336 | } | ||||||
337 | |||||||
338 | sdr::properties::ItemChangeBroadcaster aItemChange(*pObj); | ||||||
339 | |||||||
340 | // Since ClearItem sets back everything to normal | ||||||
341 | // it also sets fit-to-size text to non-fit-to-size text and | ||||||
342 | // switches on autogrowheight (the default). That may lead to | ||||||
343 | // losing the geometry size info for the object when it is | ||||||
344 | // laid out again from AdjustTextFrameWidthAndHeight(). This makes | ||||||
345 | // rescuing the size of the object necessary. | ||||||
346 | const tools::Rectangle aSnapRect = pObj->GetSnapRect(); | ||||||
347 | // SdrObjCustomShape::NbcSetSnapRect needs logic instead of snap rect | ||||||
348 | const tools::Rectangle aLogicRect = pObj->GetLogicRect(); | ||||||
349 | |||||||
350 | if(pUndoSet) | ||||||
351 | { | ||||||
352 | if(dynamic_cast<const SdrCaptionObj*>( pObj) != nullptr) | ||||||
353 | { | ||||||
354 | // do a more smooth item deletion here, else the text | ||||||
355 | // rect will be reformatted, especially when information regarding | ||||||
356 | // vertical text is changed. When clearing only set items it's | ||||||
357 | // slower, but safer regarding such information (it's not changed | ||||||
358 | // usually) | ||||||
359 | SfxWhichIter aIter(*pUndoSet); | ||||||
360 | sal_uInt16 nWhich(aIter.FirstWhich()); | ||||||
361 | |||||||
362 | while(nWhich) | ||||||
363 | { | ||||||
364 | if(SfxItemState::SET != pUndoSet->GetItemState(nWhich, false)) | ||||||
365 | { | ||||||
366 | pObj->ClearMergedItem(nWhich); | ||||||
367 | } | ||||||
368 | |||||||
369 | nWhich = aIter.NextWhich(); | ||||||
370 | } | ||||||
371 | } | ||||||
372 | else | ||||||
373 | { | ||||||
374 | pObj->ClearMergedItem(); | ||||||
375 | } | ||||||
376 | |||||||
377 | pObj->SetMergedItemSet(*pUndoSet); | ||||||
378 | } | ||||||
379 | |||||||
380 | // Restore previous size here when it was changed. | ||||||
381 | if(aSnapRect != pObj->GetSnapRect()) | ||||||
382 | { | ||||||
383 | if(dynamic_cast<const SdrObjCustomShape*>(pObj)) | ||||||
384 | pObj->NbcSetSnapRect(aLogicRect); | ||||||
385 | else | ||||||
386 | pObj->NbcSetSnapRect(aSnapRect); | ||||||
387 | } | ||||||
388 | |||||||
389 | pObj->GetProperties().BroadcastItemChange(aItemChange); | ||||||
390 | |||||||
391 | if(pTextUndo) | ||||||
392 | { | ||||||
393 | pObj->SetOutlinerParaObject(std::make_unique<OutlinerParaObject>(*pTextUndo)); | ||||||
394 | } | ||||||
395 | } | ||||||
396 | |||||||
397 | if(pUndoGroup) | ||||||
398 | { | ||||||
399 | pUndoGroup->Undo(); | ||||||
400 | } | ||||||
401 | } | ||||||
402 | |||||||
403 | void SdrUndoAttrObj::Redo() | ||||||
404 | { | ||||||
405 | E3DModifySceneSnapRectUpdater aUpdater(pObj); | ||||||
406 | bool bIs3DScene(dynamic_cast< E3dScene* >(pObj) != nullptr); | ||||||
407 | |||||||
408 | if(!pUndoGroup || bIs3DScene) | ||||||
409 | { | ||||||
410 | if(bStyleSheet) | ||||||
411 | { | ||||||
412 | mxUndoStyleSheet = pObj->GetStyleSheet(); | ||||||
413 | SfxStyleSheet* pSheet = dynamic_cast< SfxStyleSheet* >(mxRedoStyleSheet.get()); | ||||||
414 | |||||||
415 | if(pSheet && pObj->getSdrModelFromSdrObject().GetStyleSheetPool()) | ||||||
416 | { | ||||||
417 | ensureStyleSheetInStyleSheetPool(*pObj->getSdrModelFromSdrObject().GetStyleSheetPool(), *pSheet); | ||||||
418 | pObj->SetStyleSheet(pSheet, true); | ||||||
419 | } | ||||||
420 | else | ||||||
421 | { | ||||||
422 | OSL_ENSURE(false, "OOps, something went wrong in SdrUndoAttrObj (!)")do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "422" ": "), "%s", "OOps, something went wrong in SdrUndoAttrObj (!)" ); } } while (false); | ||||||
423 | } | ||||||
424 | } | ||||||
425 | |||||||
426 | sdr::properties::ItemChangeBroadcaster aItemChange(*pObj); | ||||||
427 | |||||||
428 | const tools::Rectangle aSnapRect = pObj->GetSnapRect(); | ||||||
429 | const tools::Rectangle aLogicRect = pObj->GetLogicRect(); | ||||||
430 | |||||||
431 | if(pRedoSet) | ||||||
432 | { | ||||||
433 | if(dynamic_cast<const SdrCaptionObj*>( pObj) != nullptr) | ||||||
434 | { | ||||||
435 | // do a more smooth item deletion here, else the text | ||||||
436 | // rect will be reformatted, especially when information regarding | ||||||
437 | // vertical text is changed. When clearing only set items it's | ||||||
438 | // slower, but safer regarding such information (it's not changed | ||||||
439 | // usually) | ||||||
440 | SfxWhichIter aIter(*pRedoSet); | ||||||
441 | sal_uInt16 nWhich(aIter.FirstWhich()); | ||||||
442 | |||||||
443 | while(nWhich) | ||||||
444 | { | ||||||
445 | if(SfxItemState::SET != pRedoSet->GetItemState(nWhich, false)) | ||||||
446 | { | ||||||
447 | pObj->ClearMergedItem(nWhich); | ||||||
448 | } | ||||||
449 | |||||||
450 | nWhich = aIter.NextWhich(); | ||||||
451 | } | ||||||
452 | } | ||||||
453 | else | ||||||
454 | { | ||||||
455 | pObj->ClearMergedItem(); | ||||||
456 | } | ||||||
457 | |||||||
458 | pObj->SetMergedItemSet(*pRedoSet); | ||||||
459 | } | ||||||
460 | |||||||
461 | // Restore previous size here when it was changed. | ||||||
462 | if(aSnapRect != pObj->GetSnapRect()) | ||||||
463 | { | ||||||
464 | if(dynamic_cast<const SdrObjCustomShape*>(pObj)) | ||||||
465 | pObj->NbcSetSnapRect(aLogicRect); | ||||||
466 | else | ||||||
467 | pObj->NbcSetSnapRect(aSnapRect); | ||||||
468 | } | ||||||
469 | |||||||
470 | pObj->GetProperties().BroadcastItemChange(aItemChange); | ||||||
471 | |||||||
472 | // #i8508# | ||||||
473 | if(pTextRedo) | ||||||
474 | { | ||||||
475 | pObj->SetOutlinerParaObject(std::make_unique<OutlinerParaObject>(*pTextRedo)); | ||||||
476 | } | ||||||
477 | } | ||||||
478 | |||||||
479 | if(pUndoGroup) | ||||||
480 | { | ||||||
481 | pUndoGroup->Redo(); | ||||||
482 | } | ||||||
483 | |||||||
484 | // Trigger PageChangeCall | ||||||
485 | ImpShowPageOfThisObject(); | ||||||
486 | } | ||||||
487 | |||||||
488 | OUString SdrUndoAttrObj::GetComment() const | ||||||
489 | { | ||||||
490 | if(bStyleSheet) | ||||||
491 | { | ||||||
492 | return ImpGetDescriptionStr(STR_EditSetStylesheetreinterpret_cast<char const *>("STR_EditSetStylesheet" "\004" u8"Apply Styles to %1")); | ||||||
493 | } | ||||||
494 | else | ||||||
495 | { | ||||||
496 | return ImpGetDescriptionStr(STR_EditSetAttributesreinterpret_cast<char const *>("STR_EditSetAttributes" "\004" u8"Apply attributes to %1")); | ||||||
497 | } | ||||||
498 | } | ||||||
499 | |||||||
500 | OUString SdrUndoAttrObj::GetSdrRepeatComment() const | ||||||
501 | { | ||||||
502 | if(bStyleSheet) | ||||||
503 | { | ||||||
504 | return ImpGetDescriptionStr(STR_EditSetStylesheetreinterpret_cast<char const *>("STR_EditSetStylesheet" "\004" u8"Apply Styles to %1"), true); | ||||||
505 | } | ||||||
506 | else | ||||||
507 | { | ||||||
508 | return ImpGetDescriptionStr(STR_EditSetAttributesreinterpret_cast<char const *>("STR_EditSetAttributes" "\004" u8"Apply attributes to %1"), true); | ||||||
509 | } | ||||||
510 | } | ||||||
511 | |||||||
512 | |||||||
513 | SdrUndoMoveObj::~SdrUndoMoveObj() {} | ||||||
514 | |||||||
515 | void SdrUndoMoveObj::Undo() | ||||||
516 | { | ||||||
517 | // Trigger PageChangeCall | ||||||
518 | ImpShowPageOfThisObject(); | ||||||
519 | |||||||
520 | pObj->Move(Size(-aDistance.Width(),-aDistance.Height())); | ||||||
521 | } | ||||||
522 | |||||||
523 | void SdrUndoMoveObj::Redo() | ||||||
524 | { | ||||||
525 | pObj->Move(Size(aDistance.Width(),aDistance.Height())); | ||||||
526 | |||||||
527 | // Trigger PageChangeCall | ||||||
528 | ImpShowPageOfThisObject(); | ||||||
529 | } | ||||||
530 | |||||||
531 | OUString SdrUndoMoveObj::GetComment() const | ||||||
532 | { | ||||||
533 | return ImpGetDescriptionStr(STR_EditMovereinterpret_cast<char const *>("STR_EditMove" "\004" u8"Move %1" )); | ||||||
534 | } | ||||||
535 | |||||||
536 | void SdrUndoMoveObj::SdrRepeat(SdrView& rView) | ||||||
537 | { | ||||||
538 | rView.MoveMarkedObj(aDistance); | ||||||
539 | } | ||||||
540 | |||||||
541 | bool SdrUndoMoveObj::CanSdrRepeat(SdrView& rView) const | ||||||
542 | { | ||||||
543 | return rView.AreObjectsMarked(); | ||||||
544 | } | ||||||
545 | |||||||
546 | OUString SdrUndoMoveObj::GetSdrRepeatComment() const | ||||||
547 | { | ||||||
548 | return ImpGetDescriptionStr(STR_EditMovereinterpret_cast<char const *>("STR_EditMove" "\004" u8"Move %1" ),true); | ||||||
549 | } | ||||||
550 | |||||||
551 | |||||||
552 | SdrUndoGeoObj::SdrUndoGeoObj(SdrObject& rNewObj) | ||||||
553 | : SdrUndoObj(rNewObj) | ||||||
554 | , mbSkipChangeLayout(false) | ||||||
555 | { | ||||||
556 | SdrObjList* pOL=rNewObj.GetSubList(); | ||||||
557 | if (pOL!=nullptr && pOL->GetObjCount() && dynamic_cast<const E3dScene* >( &rNewObj) == nullptr) | ||||||
558 | { | ||||||
559 | // this is a group object! | ||||||
560 | // If this were 3D scene, we'd only add an Undo for the scene itself | ||||||
561 | // (which we do elsewhere). | ||||||
562 | pUndoGroup.reset(new SdrUndoGroup(pObj->getSdrModelFromSdrObject())); | ||||||
563 | const size_t nObjCount = pOL->GetObjCount(); | ||||||
564 | for (size_t nObjNum = 0; nObjNum<nObjCount; ++nObjNum) { | ||||||
565 | pUndoGroup->AddAction(std::make_unique<SdrUndoGeoObj>(*pOL->GetObj(nObjNum))); | ||||||
566 | } | ||||||
567 | } | ||||||
568 | else | ||||||
569 | { | ||||||
570 | pUndoGeo.reset(pObj->GetGeoData()); | ||||||
571 | } | ||||||
572 | } | ||||||
573 | |||||||
574 | SdrUndoGeoObj::~SdrUndoGeoObj() | ||||||
575 | { | ||||||
576 | pUndoGeo.reset(); | ||||||
577 | pRedoGeo.reset(); | ||||||
578 | pUndoGroup.reset(); | ||||||
579 | } | ||||||
580 | |||||||
581 | void SdrUndoGeoObj::Undo() | ||||||
582 | { | ||||||
583 | // Trigger PageChangeCall | ||||||
584 | ImpShowPageOfThisObject(); | ||||||
585 | |||||||
586 | if(pUndoGroup) | ||||||
587 | { | ||||||
588 | pUndoGroup->Undo(); | ||||||
589 | |||||||
590 | // only repaint, no objectchange | ||||||
591 | pObj->ActionChanged(); | ||||||
592 | } | ||||||
593 | else | ||||||
594 | { | ||||||
595 | pRedoGeo.reset(pObj->GetGeoData()); | ||||||
596 | |||||||
597 | auto pTableObj = dynamic_cast<sdr::table::SdrTableObj*>(pObj); | ||||||
598 | if (pTableObj && mbSkipChangeLayout) | ||||||
599 | pTableObj->SetSkipChangeLayout(true); | ||||||
600 | pObj->SetGeoData(*pUndoGeo); | ||||||
601 | if (pTableObj && mbSkipChangeLayout) | ||||||
602 | pTableObj->SetSkipChangeLayout(false); | ||||||
603 | } | ||||||
604 | } | ||||||
605 | |||||||
606 | void SdrUndoGeoObj::Redo() | ||||||
607 | { | ||||||
608 | if(pUndoGroup) | ||||||
609 | { | ||||||
610 | pUndoGroup->Redo(); | ||||||
611 | |||||||
612 | // only repaint, no objectchange | ||||||
613 | pObj->ActionChanged(); | ||||||
614 | } | ||||||
615 | else | ||||||
616 | { | ||||||
617 | pUndoGeo.reset(pObj->GetGeoData()); | ||||||
618 | pObj->SetGeoData(*pRedoGeo); | ||||||
619 | } | ||||||
620 | |||||||
621 | // Trigger PageChangeCall | ||||||
622 | ImpShowPageOfThisObject(); | ||||||
623 | } | ||||||
624 | |||||||
625 | OUString SdrUndoGeoObj::GetComment() const | ||||||
626 | { | ||||||
627 | return ImpGetDescriptionStr(STR_DragMethObjOwnreinterpret_cast<char const *>("STR_DragMethObjOwn" "\004" u8"Geometrically change %1")); | ||||||
628 | } | ||||||
629 | |||||||
630 | |||||||
631 | SdrUndoObjList::SdrUndoObjList(SdrObject& rNewObj, bool bOrdNumDirect) | ||||||
632 | : SdrUndoObj(rNewObj) | ||||||
633 | , bOwner(false) | ||||||
634 | { | ||||||
635 | pObjList=pObj->getParentSdrObjListFromSdrObject(); | ||||||
636 | if (bOrdNumDirect) | ||||||
637 | { | ||||||
638 | nOrdNum=pObj->GetOrdNumDirect(); | ||||||
639 | } | ||||||
640 | else | ||||||
641 | { | ||||||
642 | nOrdNum=pObj->GetOrdNum(); | ||||||
643 | } | ||||||
644 | } | ||||||
645 | |||||||
646 | SdrUndoObjList::~SdrUndoObjList() | ||||||
647 | { | ||||||
648 | SolarMutexGuard aGuard; | ||||||
649 | |||||||
650 | if (pObj!=nullptr && IsOwner()) | ||||||
651 | { | ||||||
652 | // Attribute have to go back to the regular Pool | ||||||
653 | SetOwner(false); | ||||||
654 | |||||||
655 | // now delete | ||||||
656 | SdrObject::Free( pObj ); | ||||||
657 | } | ||||||
658 | } | ||||||
659 | |||||||
660 | void SdrUndoObjList::SetOwner(bool bNew) | ||||||
661 | { | ||||||
662 | bOwner = bNew; | ||||||
663 | } | ||||||
664 | |||||||
665 | |||||||
666 | void SdrUndoRemoveObj::Undo() | ||||||
667 | { | ||||||
668 | // Trigger PageChangeCall | ||||||
669 | ImpShowPageOfThisObject(); | ||||||
670 | |||||||
671 | DBG_ASSERT(!pObj->IsInserted(),"UndoRemoveObj: pObj has already been inserted.")do { if (true && (!(!pObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "671" ": "), "%s", "UndoRemoveObj: pObj has already been inserted." ); } } while (false); | ||||||
672 | if (pObj->IsInserted()) | ||||||
673 | return; | ||||||
674 | |||||||
675 | // #i11426# | ||||||
676 | // For UNDOs in Calc/Writer it is necessary to adapt the anchor | ||||||
677 | // position of the target object. | ||||||
678 | Point aOwnerAnchorPos(0, 0); | ||||||
679 | |||||||
680 | if (dynamic_cast< const SdrObjGroup* >(pObjList->getSdrObjectFromSdrObjList()) != nullptr) | ||||||
681 | { | ||||||
682 | aOwnerAnchorPos = pObjList->getSdrObjectFromSdrObjList()->GetAnchorPos(); | ||||||
683 | } | ||||||
684 | |||||||
685 | E3DModifySceneSnapRectUpdater aUpdater(pObjList->getSdrObjectFromSdrObjList()); | ||||||
686 | pObjList->InsertObject(pObj,nOrdNum); | ||||||
687 | |||||||
688 | // #i11426# | ||||||
689 | if(aOwnerAnchorPos.X() || aOwnerAnchorPos.Y()) | ||||||
690 | { | ||||||
691 | pObj->NbcSetAnchorPos(aOwnerAnchorPos); | ||||||
692 | } | ||||||
693 | } | ||||||
694 | |||||||
695 | void SdrUndoRemoveObj::Redo() | ||||||
696 | { | ||||||
697 | DBG_ASSERT(pObj->IsInserted(),"RedoRemoveObj: pObj is not inserted.")do { if (true && (!(pObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "697" ": "), "%s", "RedoRemoveObj: pObj is not inserted." ); } } while (false); | ||||||
698 | if (pObj->IsInserted()) | ||||||
699 | { | ||||||
700 | ImplUnmarkObject( pObj ); | ||||||
701 | E3DModifySceneSnapRectUpdater aUpdater(pObj); | ||||||
702 | pObjList->RemoveObject(pObj->GetOrdNum()); | ||||||
703 | } | ||||||
704 | |||||||
705 | // Trigger PageChangeCall | ||||||
706 | ImpShowPageOfThisObject(); | ||||||
707 | } | ||||||
708 | |||||||
709 | SdrUndoRemoveObj::~SdrUndoRemoveObj() | ||||||
710 | { | ||||||
711 | } | ||||||
712 | |||||||
713 | |||||||
714 | void SdrUndoInsertObj::Undo() | ||||||
715 | { | ||||||
716 | // Trigger PageChangeCall | ||||||
717 | ImpShowPageOfThisObject(); | ||||||
718 | |||||||
719 | DBG_ASSERT(pObj->IsInserted(),"UndoInsertObj: pObj is not inserted.")do { if (true && (!(pObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "719" ": "), "%s", "UndoInsertObj: pObj is not inserted." ); } } while (false); | ||||||
720 | if (pObj->IsInserted()) | ||||||
721 | { | ||||||
722 | ImplUnmarkObject( pObj ); | ||||||
723 | |||||||
724 | SdrObject* pChkObj= pObjList->RemoveObject(pObj->GetOrdNum()); | ||||||
725 | DBG_ASSERT(pChkObj==pObj,"UndoInsertObj: RemoveObjNum!=pObj")do { if (true && (!(pChkObj==pObj))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "725" ": "), "%s", "UndoInsertObj: RemoveObjNum!=pObj"); } } while (false); | ||||||
726 | } | ||||||
727 | } | ||||||
728 | |||||||
729 | void SdrUndoInsertObj::Redo() | ||||||
730 | { | ||||||
731 | DBG_ASSERT(!pObj->IsInserted(),"RedoInsertObj: pObj is already inserted")do { if (true && (!(!pObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "731" ": "), "%s", "RedoInsertObj: pObj is already inserted" ); } } while (false); | ||||||
732 | if (!pObj->IsInserted()) | ||||||
733 | { | ||||||
734 | // Restore anchor position of an object, | ||||||
735 | // which becomes a member of a group, because its cleared in method | ||||||
736 | // <InsertObject(..)>. Needed for correct Redo in Writer. (#i45952#) | ||||||
737 | Point aAnchorPos( 0, 0 ); | ||||||
738 | |||||||
739 | if (dynamic_cast<const SdrObjGroup*>(pObjList->getSdrObjectFromSdrObjList()) != nullptr) | ||||||
740 | { | ||||||
741 | aAnchorPos = pObj->GetAnchorPos(); | ||||||
742 | } | ||||||
743 | |||||||
744 | pObjList->InsertObject(pObj,nOrdNum); | ||||||
745 | |||||||
746 | // Arcs lose position when grouped (#i45952#) | ||||||
747 | if ( aAnchorPos.X() || aAnchorPos.Y() ) | ||||||
748 | { | ||||||
749 | pObj->NbcSetAnchorPos( aAnchorPos ); | ||||||
750 | } | ||||||
751 | } | ||||||
752 | |||||||
753 | // Trigger PageChangeCall | ||||||
754 | ImpShowPageOfThisObject(); | ||||||
755 | } | ||||||
756 | |||||||
757 | SdrUndoDelObj::SdrUndoDelObj(SdrObject& rNewObj, bool bOrdNumDirect) | ||||||
758 | : SdrUndoRemoveObj(rNewObj,bOrdNumDirect) | ||||||
759 | { | ||||||
760 | SetOwner(true); | ||||||
761 | } | ||||||
762 | |||||||
763 | void SdrUndoDelObj::Undo() | ||||||
764 | { | ||||||
765 | SdrUndoRemoveObj::Undo(); | ||||||
766 | DBG_ASSERT(IsOwner(),"UndoDeleteObj: pObj does not belong to UndoAction")do { if (true && (!(IsOwner()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "766" ": "), "%s", "UndoDeleteObj: pObj does not belong to UndoAction" ); } } while (false); | ||||||
767 | SetOwner(false); | ||||||
768 | } | ||||||
769 | |||||||
770 | void SdrUndoDelObj::Redo() | ||||||
771 | { | ||||||
772 | SdrUndoRemoveObj::Redo(); | ||||||
773 | DBG_ASSERT(!IsOwner(),"RedoDeleteObj: pObj already belongs to UndoAction")do { if (true && (!(!IsOwner()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "773" ": "), "%s", "RedoDeleteObj: pObj already belongs to UndoAction" ); } } while (false); | ||||||
774 | SetOwner(true); | ||||||
775 | } | ||||||
776 | |||||||
777 | OUString SdrUndoDelObj::GetComment() const | ||||||
778 | { | ||||||
779 | return ImpGetDescriptionStr(STR_EditDeletereinterpret_cast<char const *>("STR_EditDelete" "\004" u8"Delete %1" )); | ||||||
780 | } | ||||||
781 | |||||||
782 | void SdrUndoDelObj::SdrRepeat(SdrView& rView) | ||||||
783 | { | ||||||
784 | rView.DeleteMarked(); | ||||||
785 | } | ||||||
786 | |||||||
787 | bool SdrUndoDelObj::CanSdrRepeat(SdrView& rView) const | ||||||
788 | { | ||||||
789 | return rView.AreObjectsMarked(); | ||||||
790 | } | ||||||
791 | |||||||
792 | OUString SdrUndoDelObj::GetSdrRepeatComment() const | ||||||
793 | { | ||||||
794 | return ImpGetDescriptionStr(STR_EditDeletereinterpret_cast<char const *>("STR_EditDelete" "\004" u8"Delete %1" ),true); | ||||||
795 | } | ||||||
796 | |||||||
797 | |||||||
798 | void SdrUndoNewObj::Undo() | ||||||
799 | { | ||||||
800 | SdrUndoInsertObj::Undo(); | ||||||
801 | DBG_ASSERT(!IsOwner(),"RedoNewObj: pObj already belongs to UndoAction")do { if (true && (!(!IsOwner()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "801" ": "), "%s", "RedoNewObj: pObj already belongs to UndoAction" ); } } while (false); | ||||||
802 | SetOwner(true); | ||||||
803 | } | ||||||
804 | |||||||
805 | void SdrUndoNewObj::Redo() | ||||||
806 | { | ||||||
807 | SdrUndoInsertObj::Redo(); | ||||||
808 | DBG_ASSERT(IsOwner(),"RedoNewObj: pObj does not belong to UndoAction")do { if (true && (!(IsOwner()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "808" ": "), "%s", "RedoNewObj: pObj does not belong to UndoAction" ); } } while (false); | ||||||
809 | SetOwner(false); | ||||||
810 | } | ||||||
811 | |||||||
812 | OUString SdrUndoNewObj::GetComment( const SdrObject& _rForObject ) | ||||||
813 | { | ||||||
814 | return GetDescriptionStringForObject( _rForObject, STR_UndoInsertObjreinterpret_cast<char const *>("STR_UndoInsertObj" "\004" u8"Insert %1") ); | ||||||
815 | } | ||||||
816 | |||||||
817 | OUString SdrUndoNewObj::GetComment() const | ||||||
818 | { | ||||||
819 | return ImpGetDescriptionStr(STR_UndoInsertObjreinterpret_cast<char const *>("STR_UndoInsertObj" "\004" u8"Insert %1")); | ||||||
820 | } | ||||||
821 | |||||||
822 | SdrUndoReplaceObj::SdrUndoReplaceObj(SdrObject& rOldObj1, SdrObject& rNewObj1) | ||||||
823 | : SdrUndoObj(rOldObj1) | ||||||
824 | , bOldOwner(false) | ||||||
825 | , bNewOwner(false) | ||||||
826 | , pNewObj(&rNewObj1) | ||||||
827 | { | ||||||
828 | SetOldOwner(true); | ||||||
829 | pObjList=pObj->getParentSdrObjListFromSdrObject(); | ||||||
830 | } | ||||||
831 | |||||||
832 | SdrUndoReplaceObj::~SdrUndoReplaceObj() | ||||||
833 | { | ||||||
834 | if (pObj!=nullptr && IsOldOwner()) | ||||||
835 | { | ||||||
836 | // Attribute have to go back into the Pool | ||||||
837 | SetOldOwner(false); | ||||||
838 | |||||||
839 | // now delete | ||||||
840 | SdrObject::Free( pObj ); | ||||||
841 | } | ||||||
842 | if (pNewObj!=nullptr && IsNewOwner()) | ||||||
843 | { | ||||||
844 | // Attribute have to go back into the Pool | ||||||
845 | SetNewOwner(false); | ||||||
846 | |||||||
847 | // now delete | ||||||
848 | SdrObject::Free( pNewObj ); | ||||||
849 | } | ||||||
850 | } | ||||||
851 | |||||||
852 | void SdrUndoReplaceObj::Undo() | ||||||
853 | { | ||||||
854 | // Trigger PageChangeCall | ||||||
855 | ImpShowPageOfThisObject(); | ||||||
856 | |||||||
857 | if (IsOldOwner() && !IsNewOwner()) | ||||||
858 | { | ||||||
859 | DBG_ASSERT(!pObj->IsInserted(),"SdrUndoReplaceObj::Undo(): Old object is already inserted!")do { if (true && (!(!pObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "859" ": "), "%s", "SdrUndoReplaceObj::Undo(): Old object is already inserted!" ); } } while (false); | ||||||
860 | DBG_ASSERT(pNewObj->IsInserted(),"SdrUndoReplaceObj::Undo(): New object is not inserted!")do { if (true && (!(pNewObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "860" ": "), "%s", "SdrUndoReplaceObj::Undo(): New object is not inserted!" ); } } while (false); | ||||||
861 | SetOldOwner(false); | ||||||
862 | SetNewOwner(true); | ||||||
863 | |||||||
864 | ImplUnmarkObject( pNewObj ); | ||||||
865 | pObjList->ReplaceObject(pObj,pNewObj->GetOrdNum()); | ||||||
866 | } | ||||||
867 | else | ||||||
868 | { | ||||||
869 | OSL_FAIL("SdrUndoReplaceObj::Undo(): Wrong IsMine flags. Did you call Undo twice?")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "869" ": "), "%s", "SdrUndoReplaceObj::Undo(): Wrong IsMine flags. Did you call Undo twice?" ); } } while (false); | ||||||
870 | } | ||||||
871 | } | ||||||
872 | |||||||
873 | void SdrUndoReplaceObj::Redo() | ||||||
874 | { | ||||||
875 | if (!IsOldOwner() && IsNewOwner()) | ||||||
876 | { | ||||||
877 | DBG_ASSERT(!pNewObj->IsInserted(),"SdrUndoReplaceObj::Redo(): New object is already inserted!!")do { if (true && (!(!pNewObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "877" ": "), "%s", "SdrUndoReplaceObj::Redo(): New object is already inserted!!" ); } } while (false); | ||||||
878 | DBG_ASSERT(pObj->IsInserted(),"SdrUndoReplaceObj::Redo(): Old object is not inserted!!")do { if (true && (!(pObj->IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "878" ": "), "%s", "SdrUndoReplaceObj::Redo(): Old object is not inserted!!" ); } } while (false); | ||||||
879 | SetOldOwner(true); | ||||||
880 | SetNewOwner(false); | ||||||
881 | |||||||
882 | ImplUnmarkObject( pObj ); | ||||||
883 | pObjList->ReplaceObject(pNewObj,pObj->GetOrdNum()); | ||||||
884 | |||||||
885 | } | ||||||
886 | else | ||||||
887 | { | ||||||
888 | OSL_FAIL("SdrUndoReplaceObj::Redo(): Wrong IsMine flags. Did you call Redo twice?")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "888" ": "), "%s", "SdrUndoReplaceObj::Redo(): Wrong IsMine flags. Did you call Redo twice?" ); } } while (false); | ||||||
889 | } | ||||||
890 | |||||||
891 | // Trigger PageChangeCall | ||||||
892 | ImpShowPageOfThisObject(); | ||||||
893 | } | ||||||
894 | |||||||
895 | void SdrUndoReplaceObj::SetNewOwner(bool bNew) | ||||||
896 | { | ||||||
897 | bNewOwner = bNew; | ||||||
898 | } | ||||||
899 | |||||||
900 | void SdrUndoReplaceObj::SetOldOwner(bool bNew) | ||||||
901 | { | ||||||
902 | bOldOwner = bNew; | ||||||
903 | } | ||||||
904 | |||||||
905 | |||||||
906 | OUString SdrUndoCopyObj::GetComment() const | ||||||
907 | { | ||||||
908 | return ImpGetDescriptionStr(STR_UndoCopyObjreinterpret_cast<char const *>("STR_UndoCopyObj" "\004" u8"Copy %1")); | ||||||
909 | } | ||||||
910 | |||||||
911 | |||||||
912 | // #i11702# | ||||||
913 | |||||||
914 | SdrUndoObjectLayerChange::SdrUndoObjectLayerChange(SdrObject& rObj, SdrLayerID aOldLayer, SdrLayerID aNewLayer) | ||||||
915 | : SdrUndoObj(rObj) | ||||||
916 | , maOldLayer(aOldLayer) | ||||||
917 | , maNewLayer(aNewLayer) | ||||||
918 | { | ||||||
919 | } | ||||||
920 | |||||||
921 | void SdrUndoObjectLayerChange::Undo() | ||||||
922 | { | ||||||
923 | ImpShowPageOfThisObject(); | ||||||
924 | pObj->SetLayer(maOldLayer); | ||||||
925 | } | ||||||
926 | |||||||
927 | void SdrUndoObjectLayerChange::Redo() | ||||||
928 | { | ||||||
929 | pObj->SetLayer(maNewLayer); | ||||||
930 | ImpShowPageOfThisObject(); | ||||||
931 | } | ||||||
932 | |||||||
933 | |||||||
934 | SdrUndoObjOrdNum::SdrUndoObjOrdNum(SdrObject& rNewObj, sal_uInt32 nOldOrdNum1, sal_uInt32 nNewOrdNum1) | ||||||
935 | : SdrUndoObj(rNewObj) | ||||||
936 | , nOldOrdNum(nOldOrdNum1) | ||||||
937 | , nNewOrdNum(nNewOrdNum1) | ||||||
938 | { | ||||||
939 | } | ||||||
940 | |||||||
941 | void SdrUndoObjOrdNum::Undo() | ||||||
942 | { | ||||||
943 | // Trigger PageChangeCall | ||||||
944 | ImpShowPageOfThisObject(); | ||||||
945 | |||||||
946 | SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject(); | ||||||
947 | if (pOL==nullptr) | ||||||
948 | { | ||||||
949 | OSL_FAIL("UndoObjOrdNum: pObj does not have an ObjList.")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "949" ": "), "%s", "UndoObjOrdNum: pObj does not have an ObjList." ); } } while (false); | ||||||
950 | return; | ||||||
951 | } | ||||||
952 | pOL->SetObjectOrdNum(nNewOrdNum,nOldOrdNum); | ||||||
953 | } | ||||||
954 | |||||||
955 | void SdrUndoObjOrdNum::Redo() | ||||||
956 | { | ||||||
957 | SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject(); | ||||||
958 | if (pOL==nullptr) | ||||||
959 | { | ||||||
960 | OSL_FAIL("RedoObjOrdNum: pObj does not have an ObjList.")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "960" ": "), "%s", "RedoObjOrdNum: pObj does not have an ObjList." ); } } while (false); | ||||||
961 | return; | ||||||
962 | } | ||||||
963 | pOL->SetObjectOrdNum(nOldOrdNum,nNewOrdNum); | ||||||
964 | |||||||
965 | // Trigger PageChangeCall | ||||||
966 | ImpShowPageOfThisObject(); | ||||||
967 | } | ||||||
968 | |||||||
969 | OUString SdrUndoObjOrdNum::GetComment() const | ||||||
970 | { | ||||||
971 | return ImpGetDescriptionStr(STR_UndoObjOrdNumreinterpret_cast<char const *>("STR_UndoObjOrdNum" "\004" u8"Change object order of %1")); | ||||||
972 | } | ||||||
973 | |||||||
974 | |||||||
975 | SdrUndoObjSetText::SdrUndoObjSetText(SdrObject& rNewObj, sal_Int32 nText) | ||||||
976 | : SdrUndoObj(rNewObj) | ||||||
977 | , bNewTextAvailable(false) | ||||||
978 | , bEmptyPresObj(false) | ||||||
979 | , mnText(nText) | ||||||
980 | { | ||||||
981 | SdrText* pText = static_cast< SdrTextObj*>( &rNewObj )->getText(mnText); | ||||||
982 | if( pText && pText->GetOutlinerParaObject() ) | ||||||
983 | pOldText.reset( new OutlinerParaObject(*pText->GetOutlinerParaObject()) ); | ||||||
984 | |||||||
985 | bEmptyPresObj = rNewObj.IsEmptyPresObj(); | ||||||
986 | } | ||||||
987 | |||||||
988 | SdrUndoObjSetText::~SdrUndoObjSetText() | ||||||
989 | { | ||||||
990 | pOldText.reset(); | ||||||
991 | pNewText.reset(); | ||||||
992 | } | ||||||
993 | |||||||
994 | void SdrUndoObjSetText::AfterSetText() | ||||||
995 | { | ||||||
996 | if (!bNewTextAvailable) | ||||||
997 | { | ||||||
998 | SdrText* pText = static_cast< SdrTextObj*>( pObj )->getText(mnText); | ||||||
999 | if( pText && pText->GetOutlinerParaObject() ) | ||||||
1000 | pNewText.reset( new OutlinerParaObject(*pText->GetOutlinerParaObject()) ); | ||||||
1001 | bNewTextAvailable=true; | ||||||
1002 | } | ||||||
1003 | } | ||||||
1004 | |||||||
1005 | void SdrUndoObjSetText::Undo() | ||||||
1006 | { | ||||||
1007 | // only works with SdrTextObj | ||||||
1008 | SdrTextObj* pTarget = dynamic_cast< SdrTextObj* >(pObj); | ||||||
1009 | |||||||
1010 | if(!pTarget) | ||||||
1011 | { | ||||||
1012 | OSL_ENSURE(false, "SdrUndoObjSetText::Undo with SdrObject not based on SdrTextObj (!)")do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1012" ": "), "%s", "SdrUndoObjSetText::Undo with SdrObject not based on SdrTextObj (!)" ); } } while (false); | ||||||
1013 | return; | ||||||
1014 | } | ||||||
1015 | |||||||
1016 | // Trigger PageChangeCall | ||||||
1017 | ImpShowPageOfThisObject(); | ||||||
1018 | |||||||
1019 | // save old text for Redo | ||||||
1020 | if(!bNewTextAvailable) | ||||||
1021 | { | ||||||
1022 | AfterSetText(); | ||||||
1023 | } | ||||||
1024 | |||||||
1025 | SdrText* pText = pTarget->getText(mnText); | ||||||
1026 | if (pText) | ||||||
1027 | { | ||||||
1028 | // copy text for Undo, because the original now belongs to SetOutlinerParaObject() | ||||||
1029 | std::unique_ptr<OutlinerParaObject> pText1( pOldText ? new OutlinerParaObject(*pOldText) : nullptr ); | ||||||
1030 | pTarget->NbcSetOutlinerParaObjectForText(std::move(pText1), pText); | ||||||
1031 | } | ||||||
1032 | |||||||
1033 | pTarget->SetEmptyPresObj(bEmptyPresObj); | ||||||
1034 | pTarget->ActionChanged(); | ||||||
1035 | |||||||
1036 | // #i124389# if it's a table, also need to relayout TextFrame | ||||||
1037 | if(dynamic_cast< sdr::table::SdrTableObj* >(pTarget) != nullptr) | ||||||
1038 | { | ||||||
1039 | pTarget->NbcAdjustTextFrameWidthAndHeight(); | ||||||
1040 | } | ||||||
1041 | |||||||
1042 | // #i122410# SetOutlinerParaObject at SdrText does not trigger a | ||||||
1043 | // BroadcastObjectChange, but it is needed to make evtl. SlideSorters | ||||||
1044 | // update their preview. | ||||||
1045 | pTarget->BroadcastObjectChange(); | ||||||
1046 | } | ||||||
1047 | |||||||
1048 | void SdrUndoObjSetText::Redo() | ||||||
1049 | { | ||||||
1050 | // only works with SdrTextObj | ||||||
1051 | SdrTextObj* pTarget = dynamic_cast< SdrTextObj* >(pObj); | ||||||
1052 | |||||||
1053 | if(!pTarget) | ||||||
1054 | { | ||||||
1055 | OSL_ENSURE(false, "SdrUndoObjSetText::Redo with SdrObject not based on SdrTextObj (!)")do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1055" ": "), "%s", "SdrUndoObjSetText::Redo with SdrObject not based on SdrTextObj (!)" ); } } while (false); | ||||||
1056 | return; | ||||||
1057 | } | ||||||
1058 | |||||||
1059 | SdrText* pText = pTarget->getText(mnText); | ||||||
1060 | if (pText) | ||||||
1061 | { | ||||||
1062 | // copy text for Undo, because the original now belongs to SetOutlinerParaObject() | ||||||
1063 | std::unique_ptr<OutlinerParaObject> pText1( pNewText ? new OutlinerParaObject(*pNewText) : nullptr ); | ||||||
1064 | pTarget->NbcSetOutlinerParaObjectForText( std::move(pText1), pText ); | ||||||
1065 | } | ||||||
1066 | |||||||
1067 | pTarget->ActionChanged(); | ||||||
1068 | |||||||
1069 | // #i124389# if it's a table, also need to relayout TextFrame | ||||||
1070 | if(dynamic_cast< sdr::table::SdrTableObj* >(pTarget) != nullptr) | ||||||
1071 | { | ||||||
1072 | pTarget->NbcAdjustTextFrameWidthAndHeight(); | ||||||
1073 | } | ||||||
1074 | |||||||
1075 | // #i122410# NbcSetOutlinerParaObjectForText at SdrTextObj does not trigger a | ||||||
1076 | // BroadcastObjectChange, but it is needed to make evtl. SlideSorters | ||||||
1077 | // update their preview. | ||||||
1078 | pTarget->BroadcastObjectChange(); | ||||||
1079 | |||||||
1080 | // Trigger PageChangeCall | ||||||
1081 | ImpShowPageOfThisObject(); | ||||||
1082 | } | ||||||
1083 | |||||||
1084 | OUString SdrUndoObjSetText::GetComment() const | ||||||
1085 | { | ||||||
1086 | return ImpGetDescriptionStr(STR_UndoObjSetTextreinterpret_cast<char const *>("STR_UndoObjSetText" "\004" u8"Edit text of %1")); | ||||||
1087 | } | ||||||
1088 | |||||||
1089 | OUString SdrUndoObjSetText::GetSdrRepeatComment() const | ||||||
1090 | { | ||||||
1091 | return ImpGetDescriptionStr(STR_UndoObjSetTextreinterpret_cast<char const *>("STR_UndoObjSetText" "\004" u8"Edit text of %1")); | ||||||
1092 | } | ||||||
1093 | |||||||
1094 | void SdrUndoObjSetText::SdrRepeat(SdrView& rView) | ||||||
1095 | { | ||||||
1096 | if (!(bNewTextAvailable && rView.AreObjectsMarked())) | ||||||
1097 | return; | ||||||
1098 | |||||||
1099 | const SdrMarkList& rML=rView.GetMarkedObjectList(); | ||||||
1100 | |||||||
1101 | const bool bUndo = rView.IsUndoEnabled(); | ||||||
1102 | if( bUndo ) | ||||||
1103 | { | ||||||
1104 | OUString aStr = ImpGetDescriptionStr(STR_UndoObjSetTextreinterpret_cast<char const *>("STR_UndoObjSetText" "\004" u8"Edit text of %1")); | ||||||
1105 | rView.BegUndo(aStr); | ||||||
1106 | } | ||||||
1107 | |||||||
1108 | const size_t nCount=rML.GetMarkCount(); | ||||||
1109 | for (size_t nm=0; nm<nCount; ++nm) | ||||||
1110 | { | ||||||
1111 | SdrObject* pObj2=rML.GetMark(nm)->GetMarkedSdrObj(); | ||||||
1112 | SdrTextObj* pTextObj=dynamic_cast<SdrTextObj*>( pObj2 ); | ||||||
1113 | if (pTextObj!=nullptr) | ||||||
1114 | { | ||||||
1115 | if( bUndo ) | ||||||
1116 | rView.AddUndo(std::make_unique<SdrUndoObjSetText>(*pTextObj,0)); | ||||||
1117 | |||||||
1118 | std::unique_ptr<OutlinerParaObject> pText1; | ||||||
1119 | if (pNewText) | ||||||
1120 | pText1.reset(new OutlinerParaObject(*pNewText)); | ||||||
1121 | pTextObj->SetOutlinerParaObject(std::move(pText1)); | ||||||
1122 | } | ||||||
1123 | } | ||||||
1124 | |||||||
1125 | if( bUndo ) | ||||||
1126 | rView.EndUndo(); | ||||||
1127 | } | ||||||
1128 | |||||||
1129 | bool SdrUndoObjSetText::CanSdrRepeat(SdrView& rView) const | ||||||
1130 | { | ||||||
1131 | bool bOk = false; | ||||||
1132 | if (bNewTextAvailable && rView.AreObjectsMarked()) { | ||||||
1133 | bOk=true; | ||||||
1134 | } | ||||||
1135 | return bOk; | ||||||
1136 | } | ||||||
1137 | |||||||
1138 | // Undo/Redo for setting object's name (#i73249#) | ||||||
1139 | SdrUndoObjStrAttr::SdrUndoObjStrAttr( SdrObject& rNewObj, | ||||||
1140 | const ObjStrAttrType eObjStrAttr, | ||||||
1141 | const OUString& sOldStr, | ||||||
1142 | const OUString& sNewStr) | ||||||
1143 | : SdrUndoObj( rNewObj ) | ||||||
1144 | , meObjStrAttr( eObjStrAttr ) | ||||||
1145 | , msOldStr( sOldStr ) | ||||||
1146 | , msNewStr( sNewStr ) | ||||||
1147 | { | ||||||
1148 | } | ||||||
1149 | |||||||
1150 | void SdrUndoObjStrAttr::Undo() | ||||||
1151 | { | ||||||
1152 | ImpShowPageOfThisObject(); | ||||||
1153 | |||||||
1154 | switch ( meObjStrAttr ) | ||||||
1155 | { | ||||||
1156 | case ObjStrAttrType::Name: | ||||||
1157 | pObj->SetName( msOldStr ); | ||||||
1158 | break; | ||||||
1159 | case ObjStrAttrType::Title: | ||||||
1160 | pObj->SetTitle( msOldStr ); | ||||||
1161 | break; | ||||||
1162 | case ObjStrAttrType::Description: | ||||||
1163 | pObj->SetDescription( msOldStr ); | ||||||
1164 | break; | ||||||
1165 | } | ||||||
1166 | } | ||||||
1167 | |||||||
1168 | void SdrUndoObjStrAttr::Redo() | ||||||
1169 | { | ||||||
1170 | switch ( meObjStrAttr ) | ||||||
1171 | { | ||||||
1172 | case ObjStrAttrType::Name: | ||||||
1173 | pObj->SetName( msNewStr ); | ||||||
1174 | break; | ||||||
1175 | case ObjStrAttrType::Title: | ||||||
1176 | pObj->SetTitle( msNewStr ); | ||||||
1177 | break; | ||||||
1178 | case ObjStrAttrType::Description: | ||||||
1179 | pObj->SetDescription( msNewStr ); | ||||||
1180 | break; | ||||||
1181 | } | ||||||
1182 | |||||||
1183 | ImpShowPageOfThisObject(); | ||||||
1184 | } | ||||||
1185 | |||||||
1186 | OUString SdrUndoObjStrAttr::GetComment() const | ||||||
1187 | { | ||||||
1188 | OUString aStr; | ||||||
1189 | switch ( meObjStrAttr ) | ||||||
1190 | { | ||||||
1191 | case ObjStrAttrType::Name: | ||||||
1192 | aStr = ImpGetDescriptionStr( STR_UndoObjNamereinterpret_cast<char const *>("STR_UndoObjName" "\004" u8"Change object name of %1 to")) + | ||||||
1193 | " '" + msNewStr + "'"; | ||||||
1194 | break; | ||||||
1195 | case ObjStrAttrType::Title: | ||||||
1196 | aStr = ImpGetDescriptionStr( STR_UndoObjTitlereinterpret_cast<char const *>("STR_UndoObjTitle" "\004" u8"Change object title of %1") ); | ||||||
1197 | break; | ||||||
1198 | case ObjStrAttrType::Description: | ||||||
1199 | aStr = ImpGetDescriptionStr( STR_UndoObjDescriptionreinterpret_cast<char const *>("STR_UndoObjDescription" "\004" u8"Change object description of %1") ); | ||||||
1200 | break; | ||||||
1201 | } | ||||||
1202 | |||||||
1203 | return aStr; | ||||||
1204 | } | ||||||
1205 | |||||||
1206 | |||||||
1207 | SdrUndoLayer::SdrUndoLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel) | ||||||
1208 | : SdrUndoAction(rNewModel) | ||||||
1209 | , pLayer(rNewLayerAdmin.GetLayer(nLayerNum)) | ||||||
1210 | , pLayerAdmin(&rNewLayerAdmin) | ||||||
1211 | , nNum(nLayerNum) | ||||||
1212 | , bItsMine(false) | ||||||
1213 | { | ||||||
1214 | } | ||||||
1215 | |||||||
1216 | SdrUndoLayer::~SdrUndoLayer() | ||||||
1217 | { | ||||||
1218 | if (bItsMine) | ||||||
1219 | { | ||||||
1220 | delete pLayer; | ||||||
1221 | } | ||||||
1222 | } | ||||||
1223 | |||||||
1224 | |||||||
1225 | void SdrUndoNewLayer::Undo() | ||||||
1226 | { | ||||||
1227 | DBG_ASSERT(!bItsMine,"SdrUndoNewLayer::Undo(): Layer already belongs to UndoAction.")do { if (true && (!(!bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1227" ": "), "%s", "SdrUndoNewLayer::Undo(): Layer already belongs to UndoAction." ); } } while (false); | ||||||
1228 | bItsMine=true; | ||||||
1229 | SdrLayer* pCmpLayer= pLayerAdmin->RemoveLayer(nNum).release(); | ||||||
1230 | DBG_ASSERT(pCmpLayer==pLayer,"SdrUndoNewLayer::Undo(): Removed layer is != pLayer.")do { if (true && (!(pCmpLayer==pLayer))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1230" ": "), "%s", "SdrUndoNewLayer::Undo(): Removed layer is != pLayer." ); } } while (false); | ||||||
1231 | } | ||||||
1232 | |||||||
1233 | void SdrUndoNewLayer::Redo() | ||||||
1234 | { | ||||||
1235 | DBG_ASSERT(bItsMine,"SdrUndoNewLayer::Undo(): Layer does not belong to UndoAction.")do { if (true && (!(bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1235" ": "), "%s", "SdrUndoNewLayer::Undo(): Layer does not belong to UndoAction." ); } } while (false); | ||||||
1236 | bItsMine=false; | ||||||
1237 | pLayerAdmin->InsertLayer(std::unique_ptr<SdrLayer>(pLayer),nNum); | ||||||
1238 | } | ||||||
1239 | |||||||
1240 | OUString SdrUndoNewLayer::GetComment() const | ||||||
1241 | { | ||||||
1242 | return SvxResId(STR_UndoNewLayerreinterpret_cast<char const *>("STR_UndoNewLayer" "\004" u8"Insert Layer")); | ||||||
1243 | } | ||||||
1244 | |||||||
1245 | |||||||
1246 | void SdrUndoDelLayer::Undo() | ||||||
1247 | { | ||||||
1248 | DBG_ASSERT(bItsMine,"SdrUndoDelLayer::Undo(): Layer does not belong to UndoAction.")do { if (true && (!(bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1248" ": "), "%s", "SdrUndoDelLayer::Undo(): Layer does not belong to UndoAction." ); } } while (false); | ||||||
1249 | bItsMine=false; | ||||||
1250 | pLayerAdmin->InsertLayer(std::unique_ptr<SdrLayer>(pLayer),nNum); | ||||||
1251 | } | ||||||
1252 | |||||||
1253 | void SdrUndoDelLayer::Redo() | ||||||
1254 | { | ||||||
1255 | DBG_ASSERT(!bItsMine,"SdrUndoDelLayer::Undo(): Layer already belongs to UndoAction.")do { if (true && (!(!bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1255" ": "), "%s", "SdrUndoDelLayer::Undo(): Layer already belongs to UndoAction." ); } } while (false); | ||||||
1256 | bItsMine=true; | ||||||
1257 | SdrLayer* pCmpLayer= pLayerAdmin->RemoveLayer(nNum).release(); | ||||||
1258 | DBG_ASSERT(pCmpLayer==pLayer,"SdrUndoDelLayer::Redo(): Removed layer is != pLayer.")do { if (true && (!(pCmpLayer==pLayer))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1258" ": "), "%s", "SdrUndoDelLayer::Redo(): Removed layer is != pLayer." ); } } while (false); | ||||||
1259 | } | ||||||
1260 | |||||||
1261 | OUString SdrUndoDelLayer::GetComment() const | ||||||
1262 | { | ||||||
1263 | return SvxResId(STR_UndoDelLayerreinterpret_cast<char const *>("STR_UndoDelLayer" "\004" u8"Delete layer")); | ||||||
1264 | } | ||||||
1265 | |||||||
1266 | |||||||
1267 | SdrUndoPage::SdrUndoPage(SdrPage& rNewPg) | ||||||
1268 | : SdrUndoAction(rNewPg.getSdrModelFromSdrPage()) | ||||||
1269 | ,mrPage(rNewPg) | ||||||
1270 | { | ||||||
1271 | } | ||||||
1272 | |||||||
1273 | void SdrUndoPage::ImpInsertPage(sal_uInt16 nNum) | ||||||
1274 | { | ||||||
1275 | DBG_ASSERT(!mrPage.IsInserted(),"SdrUndoPage::ImpInsertPage(): mrPage is already inserted.")do { if (true && (!(!mrPage.IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1275" ": "), "%s", "SdrUndoPage::ImpInsertPage(): mrPage is already inserted." ); } } while (false); | ||||||
1276 | if (!mrPage.IsInserted()) | ||||||
1277 | { | ||||||
1278 | if (mrPage.IsMasterPage()) | ||||||
1279 | { | ||||||
1280 | rMod.InsertMasterPage(&mrPage,nNum); | ||||||
1281 | } | ||||||
1282 | else | ||||||
1283 | { | ||||||
1284 | rMod.InsertPage(&mrPage,nNum); | ||||||
1285 | } | ||||||
1286 | } | ||||||
1287 | } | ||||||
1288 | |||||||
1289 | void SdrUndoPage::ImpRemovePage(sal_uInt16 nNum) | ||||||
1290 | { | ||||||
1291 | DBG_ASSERT(mrPage.IsInserted(),"SdrUndoPage::ImpRemovePage(): mrPage is not inserted.")do { if (true && (!(mrPage.IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1291" ": "), "%s", "SdrUndoPage::ImpRemovePage(): mrPage is not inserted." ); } } while (false); | ||||||
1292 | if (!mrPage.IsInserted()) | ||||||
1293 | return; | ||||||
1294 | |||||||
1295 | SdrPage* pChkPg=nullptr; | ||||||
1296 | if (mrPage.IsMasterPage()) | ||||||
1297 | { | ||||||
1298 | pChkPg=rMod.RemoveMasterPage(nNum); | ||||||
1299 | } | ||||||
1300 | else | ||||||
1301 | { | ||||||
1302 | pChkPg=rMod.RemovePage(nNum); | ||||||
1303 | } | ||||||
1304 | DBG_ASSERT(pChkPg==&mrPage,"SdrUndoPage::ImpRemovePage(): RemovePage!=&mrPage")do { if (true && (!(pChkPg==&mrPage))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1304" ": "), "%s", "SdrUndoPage::ImpRemovePage(): RemovePage!=&mrPage" ); } } while (false); | ||||||
1305 | } | ||||||
1306 | |||||||
1307 | void SdrUndoPage::ImpMovePage(sal_uInt16 nOldNum, sal_uInt16 nNewNum) | ||||||
1308 | { | ||||||
1309 | DBG_ASSERT(mrPage.IsInserted(),"SdrUndoPage::ImpMovePage(): mrPage is not inserted.")do { if (true && (!(mrPage.IsInserted()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1309" ": "), "%s", "SdrUndoPage::ImpMovePage(): mrPage is not inserted." ); } } while (false); | ||||||
1310 | if (mrPage.IsInserted()) | ||||||
1311 | { | ||||||
1312 | if (mrPage.IsMasterPage()) | ||||||
1313 | { | ||||||
1314 | rMod.MoveMasterPage(nOldNum,nNewNum); | ||||||
1315 | } | ||||||
1316 | else | ||||||
1317 | { | ||||||
1318 | rMod.MovePage(nOldNum,nNewNum); | ||||||
1319 | } | ||||||
1320 | } | ||||||
1321 | } | ||||||
1322 | |||||||
1323 | OUString SdrUndoPage::ImpGetDescriptionStr(const char* pStrCacheID) | ||||||
1324 | { | ||||||
1325 | return SvxResId(pStrCacheID); | ||||||
1326 | } | ||||||
1327 | |||||||
1328 | |||||||
1329 | SdrUndoPageList::SdrUndoPageList(SdrPage& rNewPg) | ||||||
1330 | : SdrUndoPage(rNewPg) | ||||||
1331 | , bItsMine(false) | ||||||
1332 | { | ||||||
1333 | nPageNum=rNewPg.GetPageNum(); | ||||||
1334 | } | ||||||
1335 | |||||||
1336 | SdrUndoPageList::~SdrUndoPageList() | ||||||
1337 | { | ||||||
1338 | if(bItsMine) | ||||||
1339 | { | ||||||
1340 | delete &mrPage; | ||||||
1341 | } | ||||||
1342 | } | ||||||
1343 | |||||||
1344 | |||||||
1345 | SdrUndoDelPage::SdrUndoDelPage(SdrPage& rNewPg) | ||||||
1346 | : SdrUndoPageList(rNewPg) | ||||||
1347 | , mbHasFillBitmap(false) | ||||||
1348 | { | ||||||
1349 | bItsMine = true; | ||||||
1350 | |||||||
1351 | // keep fill bitmap separately to remove it from pool if not used elsewhere | ||||||
1352 | if (mrPage.IsMasterPage()) | ||||||
1353 | { | ||||||
1354 | SfxStyleSheet* const pStyleSheet = mrPage.getSdrPageProperties().GetStyleSheet(); | ||||||
1355 | if (pStyleSheet) | ||||||
1356 | queryFillBitmap(pStyleSheet->GetItemSet()); | ||||||
1357 | } | ||||||
1358 | else | ||||||
1359 | { | ||||||
1360 | queryFillBitmap(mrPage.getSdrPageProperties().GetItemSet()); | ||||||
1361 | } | ||||||
1362 | if (bool(mpFillBitmapItem)) | ||||||
1363 | clearFillBitmap(); | ||||||
1364 | |||||||
1365 | // now remember the master page relationships | ||||||
1366 | if(!mrPage.IsMasterPage()) | ||||||
1367 | return; | ||||||
1368 | |||||||
1369 | sal_uInt16 nPageCnt(rMod.GetPageCount()); | ||||||
1370 | |||||||
1371 | for(sal_uInt16 nPageNum2(0); nPageNum2 < nPageCnt; nPageNum2++) | ||||||
1372 | { | ||||||
1373 | SdrPage* pDrawPage = rMod.GetPage(nPageNum2); | ||||||
1374 | |||||||
1375 | if(pDrawPage->TRG_HasMasterPage()) | ||||||
1376 | { | ||||||
1377 | SdrPage& rMasterPage = pDrawPage->TRG_GetMasterPage(); | ||||||
1378 | |||||||
1379 | if(&mrPage == &rMasterPage) | ||||||
1380 | { | ||||||
1381 | if(!pUndoGroup) | ||||||
1382 | { | ||||||
1383 | pUndoGroup.reset( new SdrUndoGroup(rMod) ); | ||||||
1384 | } | ||||||
1385 | |||||||
1386 | pUndoGroup->AddAction(rMod.GetSdrUndoFactory().CreateUndoPageRemoveMasterPage(*pDrawPage)); | ||||||
1387 | } | ||||||
1388 | } | ||||||
1389 | } | ||||||
1390 | } | ||||||
1391 | |||||||
1392 | SdrUndoDelPage::~SdrUndoDelPage() | ||||||
1393 | { | ||||||
1394 | } | ||||||
1395 | |||||||
1396 | void SdrUndoDelPage::Undo() | ||||||
1397 | { | ||||||
1398 | if (bool(mpFillBitmapItem)) | ||||||
1399 | restoreFillBitmap(); | ||||||
1400 | ImpInsertPage(nPageNum); | ||||||
1401 | if (pUndoGroup!=nullptr) | ||||||
1402 | { | ||||||
1403 | // recover master page relationships | ||||||
1404 | pUndoGroup->Undo(); | ||||||
1405 | } | ||||||
1406 | DBG_ASSERT(bItsMine,"UndoDeletePage: mrPage does not belong to UndoAction.")do { if (true && (!(bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1406" ": "), "%s", "UndoDeletePage: mrPage does not belong to UndoAction." ); } } while (false); | ||||||
1407 | bItsMine=false; | ||||||
1408 | } | ||||||
1409 | |||||||
1410 | void SdrUndoDelPage::Redo() | ||||||
1411 | { | ||||||
1412 | ImpRemovePage(nPageNum); | ||||||
1413 | if (bool(mpFillBitmapItem)) | ||||||
1414 | clearFillBitmap(); | ||||||
1415 | // master page relations are dissolved automatically | ||||||
1416 | DBG_ASSERT(!bItsMine,"RedoDeletePage: mrPage already belongs to UndoAction.")do { if (true && (!(!bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1416" ": "), "%s", "RedoDeletePage: mrPage already belongs to UndoAction." ); } } while (false); | ||||||
1417 | bItsMine=true; | ||||||
1418 | } | ||||||
1419 | |||||||
1420 | OUString SdrUndoDelPage::GetComment() const | ||||||
1421 | { | ||||||
1422 | return ImpGetDescriptionStr(STR_UndoDelPagereinterpret_cast<char const *>("STR_UndoDelPage" "\004" u8"Delete page")); | ||||||
1423 | } | ||||||
1424 | |||||||
1425 | OUString SdrUndoDelPage::GetSdrRepeatComment() const | ||||||
1426 | { | ||||||
1427 | return ImpGetDescriptionStr(STR_UndoDelPagereinterpret_cast<char const *>("STR_UndoDelPage" "\004" u8"Delete page")); | ||||||
1428 | } | ||||||
1429 | |||||||
1430 | void SdrUndoDelPage::SdrRepeat(SdrView& /*rView*/) | ||||||
1431 | { | ||||||
1432 | } | ||||||
1433 | |||||||
1434 | bool SdrUndoDelPage::CanSdrRepeat(SdrView& /*rView*/) const | ||||||
1435 | { | ||||||
1436 | return false; | ||||||
1437 | } | ||||||
1438 | |||||||
1439 | void SdrUndoDelPage::queryFillBitmap(const SfxItemSet& rItemSet) | ||||||
1440 | { | ||||||
1441 | const SfxPoolItem *pItem = nullptr; | ||||||
1442 | if (rItemSet.GetItemState(XATTR_FILLBITMAP, false, &pItem) == SfxItemState::SET) | ||||||
1443 | mpFillBitmapItem.reset(pItem->Clone()); | ||||||
1444 | if (rItemSet.GetItemState(XATTR_FILLSTYLE, false, &pItem) == SfxItemState::SET) | ||||||
1445 | mbHasFillBitmap = static_cast<const XFillStyleItem*>(pItem)->GetValue() == css::drawing::FillStyle_BITMAP; | ||||||
1446 | } | ||||||
1447 | |||||||
1448 | void SdrUndoDelPage::clearFillBitmap() | ||||||
1449 | { | ||||||
1450 | if (mrPage.IsMasterPage()) | ||||||
1451 | { | ||||||
1452 | SfxStyleSheet* const pStyleSheet = mrPage.getSdrPageProperties().GetStyleSheet(); | ||||||
1453 | assert(bool(pStyleSheet))(static_cast <bool> (bool(pStyleSheet)) ? void (0) : __assert_fail ("bool(pStyleSheet)", "/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" , 1453, __extension__ __PRETTY_FUNCTION__)); // who took away my stylesheet? | ||||||
1454 | if (pStyleSheet->GetListenerCount() == 1) | ||||||
1455 | { | ||||||
1456 | SfxItemSet& rItemSet = pStyleSheet->GetItemSet(); | ||||||
1457 | rItemSet.ClearItem(XATTR_FILLBITMAP); | ||||||
1458 | if (mbHasFillBitmap) | ||||||
1459 | rItemSet.ClearItem(XATTR_FILLSTYLE); | ||||||
1460 | } | ||||||
1461 | } | ||||||
1462 | else | ||||||
1463 | { | ||||||
1464 | SdrPageProperties &rPageProps = mrPage.getSdrPageProperties(); | ||||||
1465 | rPageProps.ClearItem(XATTR_FILLBITMAP); | ||||||
1466 | if (mbHasFillBitmap) | ||||||
1467 | rPageProps.ClearItem(XATTR_FILLSTYLE); | ||||||
1468 | } | ||||||
1469 | } | ||||||
1470 | |||||||
1471 | void SdrUndoDelPage::restoreFillBitmap() | ||||||
1472 | { | ||||||
1473 | if (mrPage.IsMasterPage()) | ||||||
1474 | { | ||||||
1475 | SfxStyleSheet* const pStyleSheet = mrPage.getSdrPageProperties().GetStyleSheet(); | ||||||
1476 | assert(bool(pStyleSheet))(static_cast <bool> (bool(pStyleSheet)) ? void (0) : __assert_fail ("bool(pStyleSheet)", "/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" , 1476, __extension__ __PRETTY_FUNCTION__)); // who took away my stylesheet? | ||||||
1477 | if (pStyleSheet->GetListenerCount() == 1) | ||||||
1478 | { | ||||||
1479 | SfxItemSet& rItemSet = pStyleSheet->GetItemSet(); | ||||||
1480 | rItemSet.Put(*mpFillBitmapItem); | ||||||
1481 | if (mbHasFillBitmap) | ||||||
1482 | rItemSet.Put(XFillStyleItem(css::drawing::FillStyle_BITMAP)); | ||||||
1483 | } | ||||||
1484 | } | ||||||
1485 | else | ||||||
1486 | { | ||||||
1487 | SdrPageProperties &rPageProps = mrPage.getSdrPageProperties(); | ||||||
1488 | rPageProps.PutItem(*mpFillBitmapItem); | ||||||
1489 | if (mbHasFillBitmap) | ||||||
1490 | rPageProps.PutItem(XFillStyleItem(css::drawing::FillStyle_BITMAP)); | ||||||
1491 | } | ||||||
1492 | } | ||||||
1493 | |||||||
1494 | |||||||
1495 | void SdrUndoNewPage::Undo() | ||||||
1496 | { | ||||||
1497 | ImpRemovePage(nPageNum); | ||||||
1498 | DBG_ASSERT(!bItsMine,"UndoNewPage: mrPage already belongs to UndoAction.")do { if (true && (!(!bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1498" ": "), "%s", "UndoNewPage: mrPage already belongs to UndoAction." ); } } while (false); | ||||||
1499 | bItsMine=true; | ||||||
1500 | } | ||||||
1501 | |||||||
1502 | void SdrUndoNewPage::Redo() | ||||||
1503 | { | ||||||
1504 | ImpInsertPage(nPageNum); | ||||||
1505 | DBG_ASSERT(bItsMine,"RedoNewPage: mrPage does not belong to UndoAction.")do { if (true && (!(bItsMine))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdundo.cxx" ":" "1505" ": "), "%s", "RedoNewPage: mrPage does not belong to UndoAction." ); } } while (false); | ||||||
1506 | bItsMine=false; | ||||||
1507 | } | ||||||
1508 | |||||||
1509 | OUString SdrUndoNewPage::GetComment() const | ||||||
1510 | { | ||||||
1511 | return ImpGetDescriptionStr(STR_UndoNewPagereinterpret_cast<char const *>("STR_UndoNewPage" "\004" u8"Insert page")); | ||||||
1512 | } | ||||||
1513 | |||||||
1514 | |||||||
1515 | OUString SdrUndoCopyPage::GetComment() const | ||||||
1516 | { | ||||||
1517 | return ImpGetDescriptionStr(STR_UndoCopPagereinterpret_cast<char const *>("STR_UndoCopPage" "\004" u8"Copy page")); | ||||||
1518 | } | ||||||
1519 | |||||||
1520 | OUString SdrUndoCopyPage::GetSdrRepeatComment() const | ||||||
1521 | { | ||||||
1522 | return ImpGetDescriptionStr(STR_UndoCopPagereinterpret_cast<char const *>("STR_UndoCopPage" "\004" u8"Copy page")); | ||||||
1523 | } | ||||||
1524 | |||||||
1525 | void SdrUndoCopyPage::SdrRepeat(SdrView& /*rView*/) | ||||||
1526 | { | ||||||
1527 | |||||||
1528 | } | ||||||
1529 | |||||||
1530 | bool SdrUndoCopyPage::CanSdrRepeat(SdrView& /*rView*/) const | ||||||
1531 | { | ||||||
1532 | return false; | ||||||
1533 | } | ||||||
1534 | |||||||
1535 | |||||||
1536 | void SdrUndoSetPageNum::Undo() | ||||||
1537 | { | ||||||
1538 | ImpMovePage(nNewPageNum,nOldPageNum); | ||||||
1539 | } | ||||||
1540 | |||||||
1541 | void SdrUndoSetPageNum::Redo() | ||||||
1542 | { | ||||||
1543 | ImpMovePage(nOldPageNum,nNewPageNum); | ||||||
1544 | } | ||||||
1545 | |||||||
1546 | OUString SdrUndoSetPageNum::GetComment() const | ||||||
1547 | { | ||||||
1548 | return ImpGetDescriptionStr(STR_UndoMovPagereinterpret_cast<char const *>("STR_UndoMovPage" "\004" u8"Change order of pages")); | ||||||
1549 | } | ||||||
1550 | |||||||
1551 | SdrUndoPageMasterPage::SdrUndoPageMasterPage(SdrPage& rChangedPage) | ||||||
1552 | : SdrUndoPage(rChangedPage) | ||||||
1553 | , mbOldHadMasterPage(mrPage.TRG_HasMasterPage()) | ||||||
1554 | , maOldMasterPageNumber(0) | ||||||
1555 | { | ||||||
1556 | // get current state from page | ||||||
1557 | if(mbOldHadMasterPage) | ||||||
1558 | { | ||||||
1559 | maOldSet = mrPage.TRG_GetMasterPageVisibleLayers(); | ||||||
1560 | maOldMasterPageNumber = mrPage.TRG_GetMasterPage().GetPageNum(); | ||||||
1561 | } | ||||||
1562 | } | ||||||
1563 | |||||||
1564 | SdrUndoPageMasterPage::~SdrUndoPageMasterPage() | ||||||
1565 | { | ||||||
1566 | } | ||||||
1567 | |||||||
1568 | SdrUndoPageRemoveMasterPage::SdrUndoPageRemoveMasterPage(SdrPage& rChangedPage) | ||||||
1569 | : SdrUndoPageMasterPage(rChangedPage) | ||||||
1570 | { | ||||||
1571 | } | ||||||
1572 | |||||||
1573 | void SdrUndoPageRemoveMasterPage::Undo() | ||||||
1574 | { | ||||||
1575 | if(mbOldHadMasterPage) | ||||||
1576 | { | ||||||
1577 | mrPage.TRG_SetMasterPage(*mrPage.getSdrModelFromSdrPage().GetMasterPage(maOldMasterPageNumber)); | ||||||
1578 | mrPage.TRG_SetMasterPageVisibleLayers(maOldSet); | ||||||
1579 | } | ||||||
1580 | } | ||||||
1581 | |||||||
1582 | void SdrUndoPageRemoveMasterPage::Redo() | ||||||
1583 | { | ||||||
1584 | mrPage.TRG_ClearMasterPage(); | ||||||
1585 | } | ||||||
1586 | |||||||
1587 | OUString SdrUndoPageRemoveMasterPage::GetComment() const | ||||||
1588 | { | ||||||
1589 | return ImpGetDescriptionStr(STR_UndoDelPageMasterDscrreinterpret_cast<char const *>("STR_UndoDelPageMasterDscr" "\004" u8"Clear background page assignment")); | ||||||
1590 | } | ||||||
1591 | |||||||
1592 | SdrUndoPageChangeMasterPage::SdrUndoPageChangeMasterPage(SdrPage& rChangedPage) | ||||||
1593 | : SdrUndoPageMasterPage(rChangedPage) | ||||||
1594 | , mbNewHadMasterPage(false) | ||||||
1595 | , maNewMasterPageNumber(0) | ||||||
1596 | { | ||||||
1597 | } | ||||||
1598 | |||||||
1599 | void SdrUndoPageChangeMasterPage::Undo() | ||||||
1600 | { | ||||||
1601 | // remember values from new page | ||||||
1602 | if(mrPage.TRG_HasMasterPage()) | ||||||
1603 | { | ||||||
1604 | mbNewHadMasterPage = true; | ||||||
1605 | maNewSet = mrPage.TRG_GetMasterPageVisibleLayers(); | ||||||
1606 | maNewMasterPageNumber = mrPage.TRG_GetMasterPage().GetPageNum(); | ||||||
1607 | } | ||||||
1608 | |||||||
1609 | // restore old values | ||||||
1610 | if(mbOldHadMasterPage) | ||||||
1611 | { | ||||||
1612 | mrPage.TRG_ClearMasterPage(); | ||||||
1613 | mrPage.TRG_SetMasterPage(*mrPage.getSdrModelFromSdrPage().GetMasterPage(maOldMasterPageNumber)); | ||||||
1614 | mrPage.TRG_SetMasterPageVisibleLayers(maOldSet); | ||||||
1615 | } | ||||||
1616 | } | ||||||
1617 | |||||||
1618 | void SdrUndoPageChangeMasterPage::Redo() | ||||||
1619 | { | ||||||
1620 | // restore new values | ||||||
1621 | if(mbNewHadMasterPage) | ||||||
1622 | { | ||||||
1623 | mrPage.TRG_ClearMasterPage(); | ||||||
1624 | mrPage.TRG_SetMasterPage(*mrPage.getSdrModelFromSdrPage().GetMasterPage(maNewMasterPageNumber)); | ||||||
1625 | mrPage.TRG_SetMasterPageVisibleLayers(maNewSet); | ||||||
1626 | } | ||||||
1627 | } | ||||||
1628 | |||||||
1629 | OUString SdrUndoPageChangeMasterPage::GetComment() const | ||||||
1630 | { | ||||||
1631 | return ImpGetDescriptionStr(STR_UndoChgPageMasterDscrreinterpret_cast<char const *>("STR_UndoChgPageMasterDscr" "\004" u8"Change background page assignment")); | ||||||
1632 | } | ||||||
1633 | |||||||
1634 | |||||||
1635 | SdrUndoFactory::~SdrUndoFactory(){} | ||||||
1636 | |||||||
1637 | // shapes | ||||||
1638 | |||||||
1639 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoMoveObject( SdrObject& rObject, const Size& rDist ) | ||||||
1640 | { | ||||||
1641 | return std::make_unique<SdrUndoMoveObj>( rObject, rDist ); | ||||||
1642 | } | ||||||
1643 | |||||||
1644 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoGeoObject( SdrObject& rObject ) | ||||||
1645 | { | ||||||
1646 | return std::make_unique<SdrUndoGeoObj>( rObject ); | ||||||
1647 | } | ||||||
1648 | |||||||
1649 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoAttrObject( SdrObject& rObject, bool bStyleSheet1, bool bSaveText ) | ||||||
1650 | { | ||||||
1651 | return std::make_unique<SdrUndoAttrObj>( rObject, bStyleSheet1, bSaveText ); | ||||||
| |||||||
1652 | } | ||||||
1653 | |||||||
1654 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoRemoveObject(SdrObject& rObject) | ||||||
1655 | { | ||||||
1656 | return std::make_unique<SdrUndoRemoveObj>(rObject); | ||||||
1657 | } | ||||||
1658 | |||||||
1659 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoInsertObject( SdrObject& rObject, bool bOrdNumDirect ) | ||||||
1660 | { | ||||||
1661 | return std::make_unique<SdrUndoInsertObj>( rObject, bOrdNumDirect ); | ||||||
1662 | } | ||||||
1663 | |||||||
1664 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoDeleteObject( SdrObject& rObject, bool bOrdNumDirect ) | ||||||
1665 | { | ||||||
1666 | return std::make_unique<SdrUndoDelObj>( rObject, bOrdNumDirect ); | ||||||
1667 | } | ||||||
1668 | |||||||
1669 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoNewObject( SdrObject& rObject, bool bOrdNumDirect ) | ||||||
1670 | { | ||||||
1671 | return std::make_unique<SdrUndoNewObj>( rObject, bOrdNumDirect ); | ||||||
1672 | } | ||||||
1673 | |||||||
1674 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoCopyObject( SdrObject& rObject, bool bOrdNumDirect ) | ||||||
1675 | { | ||||||
1676 | return std::make_unique<SdrUndoCopyObj>( rObject, bOrdNumDirect ); | ||||||
1677 | } | ||||||
1678 | |||||||
1679 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoObjectOrdNum( SdrObject& rObject, sal_uInt32 nOldOrdNum1, sal_uInt32 nNewOrdNum1) | ||||||
1680 | { | ||||||
1681 | return std::make_unique<SdrUndoObjOrdNum>( rObject, nOldOrdNum1, nNewOrdNum1 ); | ||||||
1682 | } | ||||||
1683 | |||||||
1684 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject ) | ||||||
1685 | { | ||||||
1686 | return std::make_unique<SdrUndoReplaceObj>( rOldObject, rNewObject ); | ||||||
1687 | } | ||||||
1688 | |||||||
1689 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoObjectLayerChange( SdrObject& rObject, SdrLayerID aOldLayer, SdrLayerID aNewLayer ) | ||||||
1690 | { | ||||||
1691 | return std::make_unique<SdrUndoObjectLayerChange>( rObject, aOldLayer, aNewLayer ); | ||||||
1692 | } | ||||||
1693 | |||||||
1694 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoObjectSetText( SdrObject& rNewObj, sal_Int32 nText ) | ||||||
1695 | { | ||||||
1696 | return std::make_unique<SdrUndoObjSetText>( rNewObj, nText ); | ||||||
1697 | } | ||||||
1698 | |||||||
1699 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoObjectStrAttr( SdrObject& rObject, | ||||||
1700 | SdrUndoObjStrAttr::ObjStrAttrType eObjStrAttrType, | ||||||
1701 | const OUString& sOldStr, | ||||||
1702 | const OUString& sNewStr ) | ||||||
1703 | { | ||||||
1704 | return std::make_unique<SdrUndoObjStrAttr>( rObject, eObjStrAttrType, sOldStr, sNewStr ); | ||||||
1705 | } | ||||||
1706 | |||||||
1707 | |||||||
1708 | // layer | ||||||
1709 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoNewLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel) | ||||||
1710 | { | ||||||
1711 | return std::make_unique<SdrUndoNewLayer>( nLayerNum, rNewLayerAdmin, rNewModel ); | ||||||
1712 | } | ||||||
1713 | |||||||
1714 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoDeleteLayer(sal_uInt16 nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel) | ||||||
1715 | { | ||||||
1716 | return std::make_unique<SdrUndoDelLayer>( nLayerNum, rNewLayerAdmin, rNewModel ); | ||||||
1717 | } | ||||||
1718 | |||||||
1719 | // page | ||||||
1720 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoDeletePage(SdrPage& rPage) | ||||||
1721 | { | ||||||
1722 | return std::make_unique<SdrUndoDelPage>(rPage); | ||||||
1723 | } | ||||||
1724 | |||||||
1725 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoNewPage(SdrPage& rPage) | ||||||
1726 | { | ||||||
1727 | return std::make_unique<SdrUndoNewPage>( rPage ); | ||||||
1728 | } | ||||||
1729 | |||||||
1730 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoCopyPage(SdrPage& rPage) | ||||||
1731 | { | ||||||
1732 | return std::make_unique<SdrUndoCopyPage>( rPage ); | ||||||
1733 | } | ||||||
1734 | |||||||
1735 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoSetPageNum(SdrPage& rNewPg, sal_uInt16 nOldPageNum1, sal_uInt16 nNewPageNum1) | ||||||
1736 | { | ||||||
1737 | return std::make_unique<SdrUndoSetPageNum>( rNewPg, nOldPageNum1, nNewPageNum1 ); | ||||||
1738 | } | ||||||
1739 | // master page | ||||||
1740 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoPageRemoveMasterPage(SdrPage& rChangedPage) | ||||||
1741 | { | ||||||
1742 | return std::make_unique<SdrUndoPageRemoveMasterPage>( rChangedPage ); | ||||||
1743 | } | ||||||
1744 | |||||||
1745 | std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoPageChangeMasterPage(SdrPage& rChangedPage) | ||||||
1746 | { | ||||||
1747 | return std::make_unique<SdrUndoPageChangeMasterPage>(rChangedPage); | ||||||
1748 | } | ||||||
1749 | |||||||
1750 | |||||||
1751 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | // unique_ptr implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2008-2020 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 bits/unique_ptr.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{memory} |
28 | */ |
29 | |
30 | #ifndef _UNIQUE_PTR_H1 |
31 | #define _UNIQUE_PTR_H1 1 |
32 | |
33 | #include <bits/c++config.h> |
34 | #include <debug/assertions.h> |
35 | #include <type_traits> |
36 | #include <utility> |
37 | #include <tuple> |
38 | #include <bits/stl_function.h> |
39 | #include <bits/functional_hash.h> |
40 | #if __cplusplus201703L > 201703L |
41 | # include <compare> |
42 | # include <ostream> |
43 | #endif |
44 | |
45 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
46 | { |
47 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
48 | |
49 | /** |
50 | * @addtogroup pointer_abstractions |
51 | * @{ |
52 | */ |
53 | |
54 | #if _GLIBCXX_USE_DEPRECATED1 |
55 | #pragma GCC diagnostic push |
56 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
57 | template<typename> class auto_ptr; |
58 | #pragma GCC diagnostic pop |
59 | #endif |
60 | |
61 | /// Primary template of default_delete, used by unique_ptr for single objects |
62 | template<typename _Tp> |
63 | struct default_delete |
64 | { |
65 | /// Default constructor |
66 | constexpr default_delete() noexcept = default; |
67 | |
68 | /** @brief Converting constructor. |
69 | * |
70 | * Allows conversion from a deleter for objects of another type, `_Up`, |
71 | * only if `_Up*` is convertible to `_Tp*`. |
72 | */ |
73 | template<typename _Up, |
74 | typename = _Require<is_convertible<_Up*, _Tp*>>> |
75 | default_delete(const default_delete<_Up>&) noexcept { } |
76 | |
77 | /// Calls `delete __ptr` |
78 | void |
79 | operator()(_Tp* __ptr) const |
80 | { |
81 | static_assert(!is_void<_Tp>::value, |
82 | "can't delete pointer to incomplete type"); |
83 | static_assert(sizeof(_Tp)>0, |
84 | "can't delete pointer to incomplete type"); |
85 | delete __ptr; |
86 | } |
87 | }; |
88 | |
89 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
90 | // DR 740 - omit specialization for array objects with a compile time length |
91 | |
92 | /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>` |
93 | template<typename _Tp> |
94 | struct default_delete<_Tp[]> |
95 | { |
96 | public: |
97 | /// Default constructor |
98 | constexpr default_delete() noexcept = default; |
99 | |
100 | /** @brief Converting constructor. |
101 | * |
102 | * Allows conversion from a deleter for arrays of another type, such as |
103 | * a const-qualified version of `_Tp`. |
104 | * |
105 | * Conversions from types derived from `_Tp` are not allowed because |
106 | * it is undefined to `delete[]` an array of derived types through a |
107 | * pointer to the base type. |
108 | */ |
109 | template<typename _Up, |
110 | typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>> |
111 | default_delete(const default_delete<_Up[]>&) noexcept { } |
112 | |
113 | /// Calls `delete[] __ptr` |
114 | template<typename _Up> |
115 | typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type |
116 | operator()(_Up* __ptr) const |
117 | { |
118 | static_assert(sizeof(_Tp)>0, |
119 | "can't delete pointer to incomplete type"); |
120 | delete [] __ptr; |
121 | } |
122 | }; |
123 | |
124 | /// @cond undocumented |
125 | |
126 | // Manages the pointer and deleter of a unique_ptr |
127 | template <typename _Tp, typename _Dp> |
128 | class __uniq_ptr_impl |
129 | { |
130 | template <typename _Up, typename _Ep, typename = void> |
131 | struct _Ptr |
132 | { |
133 | using type = _Up*; |
134 | }; |
135 | |
136 | template <typename _Up, typename _Ep> |
137 | struct |
138 | _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> |
139 | { |
140 | using type = typename remove_reference<_Ep>::type::pointer; |
141 | }; |
142 | |
143 | public: |
144 | using _DeleterConstraint = enable_if< |
145 | __and_<__not_<is_pointer<_Dp>>, |
146 | is_default_constructible<_Dp>>::value>; |
147 | |
148 | using pointer = typename _Ptr<_Tp, _Dp>::type; |
149 | |
150 | static_assert( !is_rvalue_reference<_Dp>::value, |
151 | "unique_ptr's deleter type must be a function object type" |
152 | " or an lvalue reference type" ); |
153 | |
154 | __uniq_ptr_impl() = default; |
155 | __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } |
156 | |
157 | template<typename _Del> |
158 | __uniq_ptr_impl(pointer __p, _Del&& __d) |
159 | : _M_t(__p, std::forward<_Del>(__d)) { } |
160 | |
161 | __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept |
162 | : _M_t(std::move(__u._M_t)) |
163 | { __u._M_ptr() = nullptr; } |
164 | |
165 | __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept |
166 | { |
167 | reset(__u.release()); |
168 | _M_deleter() = std::forward<_Dp>(__u._M_deleter()); |
169 | return *this; |
170 | } |
171 | |
172 | pointer& _M_ptr() { return std::get<0>(_M_t); } |
173 | pointer _M_ptr() const { return std::get<0>(_M_t); } |
174 | _Dp& _M_deleter() { return std::get<1>(_M_t); } |
175 | const _Dp& _M_deleter() const { return std::get<1>(_M_t); } |
176 | |
177 | void reset(pointer __p) noexcept |
178 | { |
179 | const pointer __old_p = _M_ptr(); |
180 | _M_ptr() = __p; |
181 | if (__old_p) |
182 | _M_deleter()(__old_p); |
183 | } |
184 | |
185 | pointer release() noexcept |
186 | { |
187 | pointer __p = _M_ptr(); |
188 | _M_ptr() = nullptr; |
189 | return __p; |
190 | } |
191 | |
192 | void |
193 | swap(__uniq_ptr_impl& __rhs) noexcept |
194 | { |
195 | using std::swap; |
196 | swap(this->_M_ptr(), __rhs._M_ptr()); |
197 | swap(this->_M_deleter(), __rhs._M_deleter()); |
198 | } |
199 | |
200 | private: |
201 | tuple<pointer, _Dp> _M_t; |
202 | }; |
203 | |
204 | // Defines move construction + assignment as either defaulted or deleted. |
205 | template <typename _Tp, typename _Dp, |
206 | bool = is_move_constructible<_Dp>::value, |
207 | bool = is_move_assignable<_Dp>::value> |
208 | struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp> |
209 | { |
210 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
211 | __uniq_ptr_data(__uniq_ptr_data&&) = default; |
212 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; |
213 | }; |
214 | |
215 | template <typename _Tp, typename _Dp> |
216 | struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp> |
217 | { |
218 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
219 | __uniq_ptr_data(__uniq_ptr_data&&) = default; |
220 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; |
221 | }; |
222 | |
223 | template <typename _Tp, typename _Dp> |
224 | struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp> |
225 | { |
226 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
227 | __uniq_ptr_data(__uniq_ptr_data&&) = delete; |
228 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; |
229 | }; |
230 | |
231 | template <typename _Tp, typename _Dp> |
232 | struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp> |
233 | { |
234 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
235 | __uniq_ptr_data(__uniq_ptr_data&&) = delete; |
236 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; |
237 | }; |
238 | /// @endcond |
239 | |
240 | /// 20.7.1.2 unique_ptr for single objects. |
241 | template <typename _Tp, typename _Dp = default_delete<_Tp>> |
242 | class unique_ptr |
243 | { |
244 | template <typename _Up> |
245 | using _DeleterConstraint = |
246 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
247 | |
248 | __uniq_ptr_data<_Tp, _Dp> _M_t; |
249 | |
250 | public: |
251 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
252 | using element_type = _Tp; |
253 | using deleter_type = _Dp; |
254 | |
255 | private: |
256 | // helper template for detecting a safe conversion from another |
257 | // unique_ptr |
258 | template<typename _Up, typename _Ep> |
259 | using __safe_conversion_up = __and_< |
260 | is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, |
261 | __not_<is_array<_Up>> |
262 | >; |
263 | |
264 | public: |
265 | // Constructors. |
266 | |
267 | /// Default constructor, creates a unique_ptr that owns nothing. |
268 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
269 | constexpr unique_ptr() noexcept |
270 | : _M_t() |
271 | { } |
272 | |
273 | /** Takes ownership of a pointer. |
274 | * |
275 | * @param __p A pointer to an object of @c element_type |
276 | * |
277 | * The deleter will be value-initialized. |
278 | */ |
279 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
280 | explicit |
281 | unique_ptr(pointer __p) noexcept |
282 | : _M_t(__p) |
283 | { } |
284 | |
285 | /** Takes ownership of a pointer. |
286 | * |
287 | * @param __p A pointer to an object of @c element_type |
288 | * @param __d A reference to a deleter. |
289 | * |
290 | * The deleter will be initialized with @p __d |
291 | */ |
292 | template<typename _Del = deleter_type, |
293 | typename = _Require<is_copy_constructible<_Del>>> |
294 | unique_ptr(pointer __p, const deleter_type& __d) noexcept |
295 | : _M_t(__p, __d) { } |
296 | |
297 | /** Takes ownership of a pointer. |
298 | * |
299 | * @param __p A pointer to an object of @c element_type |
300 | * @param __d An rvalue reference to a (non-reference) deleter. |
301 | * |
302 | * The deleter will be initialized with @p std::move(__d) |
303 | */ |
304 | template<typename _Del = deleter_type, |
305 | typename = _Require<is_move_constructible<_Del>>> |
306 | unique_ptr(pointer __p, |
307 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
308 | _Del&&> __d) noexcept |
309 | : _M_t(__p, std::move(__d)) |
310 | { } |
311 | |
312 | template<typename _Del = deleter_type, |
313 | typename _DelUnref = typename remove_reference<_Del>::type> |
314 | unique_ptr(pointer, |
315 | __enable_if_t<is_lvalue_reference<_Del>::value, |
316 | _DelUnref&&>) = delete; |
317 | |
318 | /// Creates a unique_ptr that owns nothing. |
319 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
320 | constexpr unique_ptr(nullptr_t) noexcept |
321 | : _M_t() |
322 | { } |
323 | |
324 | // Move constructors. |
325 | |
326 | /// Move constructor. |
327 | unique_ptr(unique_ptr&&) = default; |
328 | |
329 | /** @brief Converting constructor from another type |
330 | * |
331 | * Requires that the pointer owned by @p __u is convertible to the |
332 | * type of pointer owned by this object, @p __u does not own an array, |
333 | * and @p __u has a compatible deleter type. |
334 | */ |
335 | template<typename _Up, typename _Ep, typename = _Require< |
336 | __safe_conversion_up<_Up, _Ep>, |
337 | typename conditional<is_reference<_Dp>::value, |
338 | is_same<_Ep, _Dp>, |
339 | is_convertible<_Ep, _Dp>>::type>> |
340 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
341 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
342 | { } |
343 | |
344 | #if _GLIBCXX_USE_DEPRECATED1 |
345 | #pragma GCC diagnostic push |
346 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
347 | /// Converting constructor from @c auto_ptr |
348 | template<typename _Up, typename = _Require< |
349 | is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> |
350 | unique_ptr(auto_ptr<_Up>&& __u) noexcept; |
351 | #pragma GCC diagnostic pop |
352 | #endif |
353 | |
354 | /// Destructor, invokes the deleter if the stored pointer is not null. |
355 | ~unique_ptr() noexcept |
356 | { |
357 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
358 | "unique_ptr's deleter must be invocable with a pointer"); |
359 | auto& __ptr = _M_t._M_ptr(); |
360 | if (__ptr != nullptr) |
361 | get_deleter()(std::move(__ptr)); |
362 | __ptr = pointer(); |
363 | } |
364 | |
365 | // Assignment. |
366 | |
367 | /** @brief Move assignment operator. |
368 | * |
369 | * Invokes the deleter if this object owns a pointer. |
370 | */ |
371 | unique_ptr& operator=(unique_ptr&&) = default; |
372 | |
373 | /** @brief Assignment from another type. |
374 | * |
375 | * @param __u The object to transfer ownership from, which owns a |
376 | * convertible pointer to a non-array object. |
377 | * |
378 | * Invokes the deleter if this object owns a pointer. |
379 | */ |
380 | template<typename _Up, typename _Ep> |
381 | typename enable_if< __and_< |
382 | __safe_conversion_up<_Up, _Ep>, |
383 | is_assignable<deleter_type&, _Ep&&> |
384 | >::value, |
385 | unique_ptr&>::type |
386 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
387 | { |
388 | reset(__u.release()); |
389 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
390 | return *this; |
391 | } |
392 | |
393 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
394 | unique_ptr& |
395 | operator=(nullptr_t) noexcept |
396 | { |
397 | reset(); |
398 | return *this; |
399 | } |
400 | |
401 | // Observers. |
402 | |
403 | /// Dereference the stored pointer. |
404 | typename add_lvalue_reference<element_type>::type |
405 | operator*() const |
406 | { |
407 | __glibcxx_assert(get() != pointer()); |
408 | return *get(); |
409 | } |
410 | |
411 | /// Return the stored pointer. |
412 | pointer |
413 | operator->() const noexcept |
414 | { |
415 | _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); |
416 | return get(); |
417 | } |
418 | |
419 | /// Return the stored pointer. |
420 | pointer |
421 | get() const noexcept |
422 | { return _M_t._M_ptr(); } |
423 | |
424 | /// Return a reference to the stored deleter. |
425 | deleter_type& |
426 | get_deleter() noexcept |
427 | { return _M_t._M_deleter(); } |
428 | |
429 | /// Return a reference to the stored deleter. |
430 | const deleter_type& |
431 | get_deleter() const noexcept |
432 | { return _M_t._M_deleter(); } |
433 | |
434 | /// Return @c true if the stored pointer is not null. |
435 | explicit operator bool() const noexcept |
436 | { return get() == pointer() ? false : true; } |
437 | |
438 | // Modifiers. |
439 | |
440 | /// Release ownership of any stored pointer. |
441 | pointer |
442 | release() noexcept |
443 | { return _M_t.release(); } |
444 | |
445 | /** @brief Replace the stored pointer. |
446 | * |
447 | * @param __p The new pointer to store. |
448 | * |
449 | * The deleter will be invoked if a pointer is already owned. |
450 | */ |
451 | void |
452 | reset(pointer __p = pointer()) noexcept |
453 | { |
454 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
455 | "unique_ptr's deleter must be invocable with a pointer"); |
456 | _M_t.reset(std::move(__p)); |
457 | } |
458 | |
459 | /// Exchange the pointer and deleter with another object. |
460 | void |
461 | swap(unique_ptr& __u) noexcept |
462 | { |
463 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); |
464 | _M_t.swap(__u._M_t); |
465 | } |
466 | |
467 | // Disable copy from lvalue. |
468 | unique_ptr(const unique_ptr&) = delete; |
469 | unique_ptr& operator=(const unique_ptr&) = delete; |
470 | }; |
471 | |
472 | /// 20.7.1.3 unique_ptr for array objects with a runtime length |
473 | // [unique.ptr.runtime] |
474 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
475 | // DR 740 - omit specialization for array objects with a compile time length |
476 | template<typename _Tp, typename _Dp> |
477 | class unique_ptr<_Tp[], _Dp> |
478 | { |
479 | template <typename _Up> |
480 | using _DeleterConstraint = |
481 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
482 | |
483 | __uniq_ptr_data<_Tp, _Dp> _M_t; |
484 | |
485 | template<typename _Up> |
486 | using __remove_cv = typename remove_cv<_Up>::type; |
487 | |
488 | // like is_base_of<_Tp, _Up> but false if unqualified types are the same |
489 | template<typename _Up> |
490 | using __is_derived_Tp |
491 | = __and_< is_base_of<_Tp, _Up>, |
492 | __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; |
493 | |
494 | public: |
495 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
496 | using element_type = _Tp; |
497 | using deleter_type = _Dp; |
498 | |
499 | // helper template for detecting a safe conversion from another |
500 | // unique_ptr |
501 | template<typename _Up, typename _Ep, |
502 | typename _UPtr = unique_ptr<_Up, _Ep>, |
503 | typename _UP_pointer = typename _UPtr::pointer, |
504 | typename _UP_element_type = typename _UPtr::element_type> |
505 | using __safe_conversion_up = __and_< |
506 | is_array<_Up>, |
507 | is_same<pointer, element_type*>, |
508 | is_same<_UP_pointer, _UP_element_type*>, |
509 | is_convertible<_UP_element_type(*)[], element_type(*)[]> |
510 | >; |
511 | |
512 | // helper template for detecting a safe conversion from a raw pointer |
513 | template<typename _Up> |
514 | using __safe_conversion_raw = __and_< |
515 | __or_<__or_<is_same<_Up, pointer>, |
516 | is_same<_Up, nullptr_t>>, |
517 | __and_<is_pointer<_Up>, |
518 | is_same<pointer, element_type*>, |
519 | is_convertible< |
520 | typename remove_pointer<_Up>::type(*)[], |
521 | element_type(*)[]> |
522 | > |
523 | > |
524 | >; |
525 | |
526 | // Constructors. |
527 | |
528 | /// Default constructor, creates a unique_ptr that owns nothing. |
529 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
530 | constexpr unique_ptr() noexcept |
531 | : _M_t() |
532 | { } |
533 | |
534 | /** Takes ownership of a pointer. |
535 | * |
536 | * @param __p A pointer to an array of a type safely convertible |
537 | * to an array of @c element_type |
538 | * |
539 | * The deleter will be value-initialized. |
540 | */ |
541 | template<typename _Up, |
542 | typename _Vp = _Dp, |
543 | typename = _DeleterConstraint<_Vp>, |
544 | typename = typename enable_if< |
545 | __safe_conversion_raw<_Up>::value, bool>::type> |
546 | explicit |
547 | unique_ptr(_Up __p) noexcept |
548 | : _M_t(__p) |
549 | { } |
550 | |
551 | /** Takes ownership of a pointer. |
552 | * |
553 | * @param __p A pointer to an array of a type safely convertible |
554 | * to an array of @c element_type |
555 | * @param __d A reference to a deleter. |
556 | * |
557 | * The deleter will be initialized with @p __d |
558 | */ |
559 | template<typename _Up, typename _Del = deleter_type, |
560 | typename = _Require<__safe_conversion_raw<_Up>, |
561 | is_copy_constructible<_Del>>> |
562 | unique_ptr(_Up __p, const deleter_type& __d) noexcept |
563 | : _M_t(__p, __d) { } |
564 | |
565 | /** Takes ownership of a pointer. |
566 | * |
567 | * @param __p A pointer to an array of a type safely convertible |
568 | * to an array of @c element_type |
569 | * @param __d A reference to a deleter. |
570 | * |
571 | * The deleter will be initialized with @p std::move(__d) |
572 | */ |
573 | template<typename _Up, typename _Del = deleter_type, |
574 | typename = _Require<__safe_conversion_raw<_Up>, |
575 | is_move_constructible<_Del>>> |
576 | unique_ptr(_Up __p, |
577 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
578 | _Del&&> __d) noexcept |
579 | : _M_t(std::move(__p), std::move(__d)) |
580 | { } |
581 | |
582 | template<typename _Up, typename _Del = deleter_type, |
583 | typename _DelUnref = typename remove_reference<_Del>::type, |
584 | typename = _Require<__safe_conversion_raw<_Up>>> |
585 | unique_ptr(_Up, |
586 | __enable_if_t<is_lvalue_reference<_Del>::value, |
587 | _DelUnref&&>) = delete; |
588 | |
589 | /// Move constructor. |
590 | unique_ptr(unique_ptr&&) = default; |
591 | |
592 | /// Creates a unique_ptr that owns nothing. |
593 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
594 | constexpr unique_ptr(nullptr_t) noexcept |
595 | : _M_t() |
596 | { } |
597 | |
598 | template<typename _Up, typename _Ep, typename = _Require< |
599 | __safe_conversion_up<_Up, _Ep>, |
600 | typename conditional<is_reference<_Dp>::value, |
601 | is_same<_Ep, _Dp>, |
602 | is_convertible<_Ep, _Dp>>::type>> |
603 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
604 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
605 | { } |
606 | |
607 | /// Destructor, invokes the deleter if the stored pointer is not null. |
608 | ~unique_ptr() |
609 | { |
610 | auto& __ptr = _M_t._M_ptr(); |
611 | if (__ptr != nullptr) |
612 | get_deleter()(__ptr); |
613 | __ptr = pointer(); |
614 | } |
615 | |
616 | // Assignment. |
617 | |
618 | /** @brief Move assignment operator. |
619 | * |
620 | * Invokes the deleter if this object owns a pointer. |
621 | */ |
622 | unique_ptr& |
623 | operator=(unique_ptr&&) = default; |
624 | |
625 | /** @brief Assignment from another type. |
626 | * |
627 | * @param __u The object to transfer ownership from, which owns a |
628 | * convertible pointer to an array object. |
629 | * |
630 | * Invokes the deleter if this object owns a pointer. |
631 | */ |
632 | template<typename _Up, typename _Ep> |
633 | typename |
634 | enable_if<__and_<__safe_conversion_up<_Up, _Ep>, |
635 | is_assignable<deleter_type&, _Ep&&> |
636 | >::value, |
637 | unique_ptr&>::type |
638 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
639 | { |
640 | reset(__u.release()); |
641 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
642 | return *this; |
643 | } |
644 | |
645 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
646 | unique_ptr& |
647 | operator=(nullptr_t) noexcept |
648 | { |
649 | reset(); |
650 | return *this; |
651 | } |
652 | |
653 | // Observers. |
654 | |
655 | /// Access an element of owned array. |
656 | typename std::add_lvalue_reference<element_type>::type |
657 | operator[](size_t __i) const |
658 | { |
659 | __glibcxx_assert(get() != pointer()); |
660 | return get()[__i]; |
661 | } |
662 | |
663 | /// Return the stored pointer. |
664 | pointer |
665 | get() const noexcept |
666 | { return _M_t._M_ptr(); } |
667 | |
668 | /// Return a reference to the stored deleter. |
669 | deleter_type& |
670 | get_deleter() noexcept |
671 | { return _M_t._M_deleter(); } |
672 | |
673 | /// Return a reference to the stored deleter. |
674 | const deleter_type& |
675 | get_deleter() const noexcept |
676 | { return _M_t._M_deleter(); } |
677 | |
678 | /// Return @c true if the stored pointer is not null. |
679 | explicit operator bool() const noexcept |
680 | { return get() == pointer() ? false : true; } |
681 | |
682 | // Modifiers. |
683 | |
684 | /// Release ownership of any stored pointer. |
685 | pointer |
686 | release() noexcept |
687 | { return _M_t.release(); } |
688 | |
689 | /** @brief Replace the stored pointer. |
690 | * |
691 | * @param __p The new pointer to store. |
692 | * |
693 | * The deleter will be invoked if a pointer is already owned. |
694 | */ |
695 | template <typename _Up, |
696 | typename = _Require< |
697 | __or_<is_same<_Up, pointer>, |
698 | __and_<is_same<pointer, element_type*>, |
699 | is_pointer<_Up>, |
700 | is_convertible< |
701 | typename remove_pointer<_Up>::type(*)[], |
702 | element_type(*)[] |
703 | > |
704 | > |
705 | > |
706 | >> |
707 | void |
708 | reset(_Up __p) noexcept |
709 | { _M_t.reset(std::move(__p)); } |
710 | |
711 | void reset(nullptr_t = nullptr) noexcept |
712 | { reset(pointer()); } |
713 | |
714 | /// Exchange the pointer and deleter with another object. |
715 | void |
716 | swap(unique_ptr& __u) noexcept |
717 | { |
718 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); |
719 | _M_t.swap(__u._M_t); |
720 | } |
721 | |
722 | // Disable copy from lvalue. |
723 | unique_ptr(const unique_ptr&) = delete; |
724 | unique_ptr& operator=(const unique_ptr&) = delete; |
725 | }; |
726 | |
727 | /// @relates unique_ptr @{ |
728 | |
729 | /// Swap overload for unique_ptr |
730 | template<typename _Tp, typename _Dp> |
731 | inline |
732 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
733 | // Constrained free swap overload, see p0185r1 |
734 | typename enable_if<__is_swappable<_Dp>::value>::type |
735 | #else |
736 | void |
737 | #endif |
738 | swap(unique_ptr<_Tp, _Dp>& __x, |
739 | unique_ptr<_Tp, _Dp>& __y) noexcept |
740 | { __x.swap(__y); } |
741 | |
742 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
743 | template<typename _Tp, typename _Dp> |
744 | typename enable_if<!__is_swappable<_Dp>::value>::type |
745 | swap(unique_ptr<_Tp, _Dp>&, |
746 | unique_ptr<_Tp, _Dp>&) = delete; |
747 | #endif |
748 | |
749 | /// Equality operator for unique_ptr objects, compares the owned pointers |
750 | template<typename _Tp, typename _Dp, |
751 | typename _Up, typename _Ep> |
752 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
753 | operator==(const unique_ptr<_Tp, _Dp>& __x, |
754 | const unique_ptr<_Up, _Ep>& __y) |
755 | { return __x.get() == __y.get(); } |
756 | |
757 | /// unique_ptr comparison with nullptr |
758 | template<typename _Tp, typename _Dp> |
759 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
760 | operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
761 | { return !__x; } |
762 | |
763 | #ifndef __cpp_lib_three_way_comparison |
764 | /// unique_ptr comparison with nullptr |
765 | template<typename _Tp, typename _Dp> |
766 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
767 | operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
768 | { return !__x; } |
769 | |
770 | /// Inequality operator for unique_ptr objects, compares the owned pointers |
771 | template<typename _Tp, typename _Dp, |
772 | typename _Up, typename _Ep> |
773 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
774 | operator!=(const unique_ptr<_Tp, _Dp>& __x, |
775 | const unique_ptr<_Up, _Ep>& __y) |
776 | { return __x.get() != __y.get(); } |
777 | |
778 | /// unique_ptr comparison with nullptr |
779 | template<typename _Tp, typename _Dp> |
780 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
781 | operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
782 | { return (bool)__x; } |
783 | |
784 | /// unique_ptr comparison with nullptr |
785 | template<typename _Tp, typename _Dp> |
786 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
787 | operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
788 | { return (bool)__x; } |
789 | #endif // three way comparison |
790 | |
791 | /// Relational operator for unique_ptr objects, compares the owned pointers |
792 | template<typename _Tp, typename _Dp, |
793 | typename _Up, typename _Ep> |
794 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
795 | operator<(const unique_ptr<_Tp, _Dp>& __x, |
796 | const unique_ptr<_Up, _Ep>& __y) |
797 | { |
798 | typedef typename |
799 | std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, |
800 | typename unique_ptr<_Up, _Ep>::pointer>::type _CT; |
801 | return std::less<_CT>()(__x.get(), __y.get()); |
802 | } |
803 | |
804 | /// unique_ptr comparison with nullptr |
805 | template<typename _Tp, typename _Dp> |
806 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
807 | operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
808 | { |
809 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
810 | nullptr); |
811 | } |
812 | |
813 | /// unique_ptr comparison with nullptr |
814 | template<typename _Tp, typename _Dp> |
815 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
816 | operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
817 | { |
818 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
819 | __x.get()); |
820 | } |
821 | |
822 | /// Relational operator for unique_ptr objects, compares the owned pointers |
823 | template<typename _Tp, typename _Dp, |
824 | typename _Up, typename _Ep> |
825 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
826 | operator<=(const unique_ptr<_Tp, _Dp>& __x, |
827 | const unique_ptr<_Up, _Ep>& __y) |
828 | { return !(__y < __x); } |
829 | |
830 | /// unique_ptr comparison with nullptr |
831 | template<typename _Tp, typename _Dp> |
832 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
833 | operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
834 | { return !(nullptr < __x); } |
835 | |
836 | /// unique_ptr comparison with nullptr |
837 | template<typename _Tp, typename _Dp> |
838 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
839 | operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
840 | { return !(__x < nullptr); } |
841 | |
842 | /// Relational operator for unique_ptr objects, compares the owned pointers |
843 | template<typename _Tp, typename _Dp, |
844 | typename _Up, typename _Ep> |
845 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
846 | operator>(const unique_ptr<_Tp, _Dp>& __x, |
847 | const unique_ptr<_Up, _Ep>& __y) |
848 | { return (__y < __x); } |
849 | |
850 | /// unique_ptr comparison with nullptr |
851 | template<typename _Tp, typename _Dp> |
852 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
853 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
854 | { |
855 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
856 | __x.get()); |
857 | } |
858 | |
859 | /// unique_ptr comparison with nullptr |
860 | template<typename _Tp, typename _Dp> |
861 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
862 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
863 | { |
864 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
865 | nullptr); |
866 | } |
867 | |
868 | /// Relational operator for unique_ptr objects, compares the owned pointers |
869 | template<typename _Tp, typename _Dp, |
870 | typename _Up, typename _Ep> |
871 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
872 | operator>=(const unique_ptr<_Tp, _Dp>& __x, |
873 | const unique_ptr<_Up, _Ep>& __y) |
874 | { return !(__x < __y); } |
875 | |
876 | /// unique_ptr comparison with nullptr |
877 | template<typename _Tp, typename _Dp> |
878 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
879 | operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
880 | { return !(__x < nullptr); } |
881 | |
882 | /// unique_ptr comparison with nullptr |
883 | template<typename _Tp, typename _Dp> |
884 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
885 | operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
886 | { return !(nullptr < __x); } |
887 | |
888 | #ifdef __cpp_lib_three_way_comparison |
889 | template<typename _Tp, typename _Dp, typename _Up, typename _Ep> |
890 | requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer, |
891 | typename unique_ptr<_Up, _Ep>::pointer> |
892 | inline |
893 | compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer, |
894 | typename unique_ptr<_Up, _Ep>::pointer> |
895 | operator<=>(const unique_ptr<_Tp, _Dp>& __x, |
896 | const unique_ptr<_Up, _Ep>& __y) |
897 | { return compare_three_way()(__x.get(), __y.get()); } |
898 | |
899 | template<typename _Tp, typename _Dp> |
900 | requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer> |
901 | inline |
902 | compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer> |
903 | operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
904 | { |
905 | using pointer = typename unique_ptr<_Tp, _Dp>::pointer; |
906 | return compare_three_way()(__x.get(), static_cast<pointer>(nullptr)); |
907 | } |
908 | #endif |
909 | // @} relates unique_ptr |
910 | |
911 | /// @cond undocumented |
912 | template<typename _Up, typename _Ptr = typename _Up::pointer, |
913 | bool = __poison_hash<_Ptr>::__enable_hash_call> |
914 | struct __uniq_ptr_hash |
915 | #if ! _GLIBCXX_INLINE_VERSION0 |
916 | : private __poison_hash<_Ptr> |
917 | #endif |
918 | { |
919 | size_t |
920 | operator()(const _Up& __u) const |
921 | noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>()))) |
922 | { return hash<_Ptr>()(__u.get()); } |
923 | }; |
924 | |
925 | template<typename _Up, typename _Ptr> |
926 | struct __uniq_ptr_hash<_Up, _Ptr, false> |
927 | : private __poison_hash<_Ptr> |
928 | { }; |
929 | /// @endcond |
930 | |
931 | /// std::hash specialization for unique_ptr. |
932 | template<typename _Tp, typename _Dp> |
933 | struct hash<unique_ptr<_Tp, _Dp>> |
934 | : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, |
935 | public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>> |
936 | { }; |
937 | |
938 | #if __cplusplus201703L >= 201402L |
939 | /// @relates unique_ptr @{ |
940 | #define __cpp_lib_make_unique201304 201304 |
941 | |
942 | /// @cond undocumented |
943 | |
944 | template<typename _Tp> |
945 | struct _MakeUniq |
946 | { typedef unique_ptr<_Tp> __single_object; }; |
947 | |
948 | template<typename _Tp> |
949 | struct _MakeUniq<_Tp[]> |
950 | { typedef unique_ptr<_Tp[]> __array; }; |
951 | |
952 | template<typename _Tp, size_t _Bound> |
953 | struct _MakeUniq<_Tp[_Bound]> |
954 | { struct __invalid_type { }; }; |
955 | |
956 | /// @endcond |
957 | |
958 | /// std::make_unique for single objects |
959 | template<typename _Tp, typename... _Args> |
960 | inline typename _MakeUniq<_Tp>::__single_object |
961 | make_unique(_Args&&... __args) |
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } |
963 | |
964 | /// std::make_unique for arrays of unknown bound |
965 | template<typename _Tp> |
966 | inline typename _MakeUniq<_Tp>::__array |
967 | make_unique(size_t __num) |
968 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } |
969 | |
970 | /// Disable std::make_unique for arrays of known bound |
971 | template<typename _Tp, typename... _Args> |
972 | inline typename _MakeUniq<_Tp>::__invalid_type |
973 | make_unique(_Args&&...) = delete; |
974 | // @} relates unique_ptr |
975 | #endif // C++14 |
976 | |
977 | #if __cplusplus201703L > 201703L && __cpp_concepts |
978 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
979 | // 2948. unique_ptr does not define operator<< for stream output |
980 | /// Stream output operator for unique_ptr |
981 | template<typename _CharT, typename _Traits, typename _Tp, typename _Dp> |
982 | inline basic_ostream<_CharT, _Traits>& |
983 | operator<<(basic_ostream<_CharT, _Traits>& __os, |
984 | const unique_ptr<_Tp, _Dp>& __p) |
985 | requires requires { __os << __p.get(); } |
986 | { |
987 | __os << __p.get(); |
988 | return __os; |
989 | } |
990 | #endif // C++20 |
991 | |
992 | // @} group pointer_abstractions |
993 | |
994 | #if __cplusplus201703L >= 201703L |
995 | namespace __detail::__variant |
996 | { |
997 | template<typename> struct _Never_valueless_alt; // see <variant> |
998 | |
999 | // Provide the strong exception-safety guarantee when emplacing a |
1000 | // unique_ptr into a variant. |
1001 | template<typename _Tp, typename _Del> |
1002 | struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>> |
1003 | : std::true_type |
1004 | { }; |
1005 | } // namespace __detail::__variant |
1006 | #endif // C++17 |
1007 | |
1008 | _GLIBCXX_END_NAMESPACE_VERSION |
1009 | } // namespace |
1010 | |
1011 | #endif /* _UNIQUE_PTR_H */ |
1 | // <tuple> -*- C++ -*- |
2 | |
3 | // Copyright (C) 2007-2020 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/tuple |
26 | * This is a Standard C++ Library header. |
27 | */ |
28 | |
29 | #ifndef _GLIBCXX_TUPLE1 |
30 | #define _GLIBCXX_TUPLE1 1 |
31 | |
32 | #pragma GCC system_header |
33 | |
34 | #if __cplusplus201703L < 201103L |
35 | # include <bits/c++0x_warning.h> |
36 | #else |
37 | |
38 | #include <utility> |
39 | #include <array> |
40 | #include <bits/uses_allocator.h> |
41 | #include <bits/invoke.h> |
42 | #if __cplusplus201703L > 201703L |
43 | # include <compare> |
44 | # define __cpp_lib_constexpr_tuple 201811L |
45 | #endif |
46 | |
47 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
48 | { |
49 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
50 | |
51 | /** |
52 | * @addtogroup utilities |
53 | * @{ |
54 | */ |
55 | |
56 | template<typename... _Elements> |
57 | class tuple; |
58 | |
59 | template<typename _Tp> |
60 | struct __is_empty_non_tuple : is_empty<_Tp> { }; |
61 | |
62 | // Using EBO for elements that are tuples causes ambiguous base errors. |
63 | template<typename _El0, typename... _El> |
64 | struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { }; |
65 | |
66 | // Use the Empty Base-class Optimization for empty, non-final types. |
67 | template<typename _Tp> |
68 | using __empty_not_final |
69 | = typename conditional<__is_final(_Tp), false_type, |
70 | __is_empty_non_tuple<_Tp>>::type; |
71 | |
72 | template<std::size_t _Idx, typename _Head, |
73 | bool = __empty_not_final<_Head>::value> |
74 | struct _Head_base; |
75 | |
76 | template<std::size_t _Idx, typename _Head> |
77 | struct _Head_base<_Idx, _Head, true> |
78 | : public _Head |
79 | { |
80 | constexpr _Head_base() |
81 | : _Head() { } |
82 | |
83 | constexpr _Head_base(const _Head& __h) |
84 | : _Head(__h) { } |
85 | |
86 | constexpr _Head_base(const _Head_base&) = default; |
87 | constexpr _Head_base(_Head_base&&) = default; |
88 | |
89 | template<typename _UHead> |
90 | constexpr _Head_base(_UHead&& __h) |
91 | : _Head(std::forward<_UHead>(__h)) { } |
92 | |
93 | _Head_base(allocator_arg_t, __uses_alloc0) |
94 | : _Head() { } |
95 | |
96 | template<typename _Alloc> |
97 | _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) |
98 | : _Head(allocator_arg, *__a._M_a) { } |
99 | |
100 | template<typename _Alloc> |
101 | _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) |
102 | : _Head(*__a._M_a) { } |
103 | |
104 | template<typename _UHead> |
105 | _Head_base(__uses_alloc0, _UHead&& __uhead) |
106 | : _Head(std::forward<_UHead>(__uhead)) { } |
107 | |
108 | template<typename _Alloc, typename _UHead> |
109 | _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) |
110 | : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } |
111 | |
112 | template<typename _Alloc, typename _UHead> |
113 | _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) |
114 | : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } |
115 | |
116 | static constexpr _Head& |
117 | _M_head(_Head_base& __b) noexcept { return __b; } |
118 | |
119 | static constexpr const _Head& |
120 | _M_head(const _Head_base& __b) noexcept { return __b; } |
121 | }; |
122 | |
123 | template<std::size_t _Idx, typename _Head> |
124 | struct _Head_base<_Idx, _Head, false> |
125 | { |
126 | constexpr _Head_base() |
127 | : _M_head_impl() { } |
128 | |
129 | constexpr _Head_base(const _Head& __h) |
130 | : _M_head_impl(__h) { } |
131 | |
132 | constexpr _Head_base(const _Head_base&) = default; |
133 | constexpr _Head_base(_Head_base&&) = default; |
134 | |
135 | template<typename _UHead> |
136 | constexpr _Head_base(_UHead&& __h) |
137 | : _M_head_impl(std::forward<_UHead>(__h)) { } |
138 | |
139 | _GLIBCXX20_CONSTEXPR |
140 | _Head_base(allocator_arg_t, __uses_alloc0) |
141 | : _M_head_impl() { } |
142 | |
143 | template<typename _Alloc> |
144 | _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) |
145 | : _M_head_impl(allocator_arg, *__a._M_a) { } |
146 | |
147 | template<typename _Alloc> |
148 | _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) |
149 | : _M_head_impl(*__a._M_a) { } |
150 | |
151 | template<typename _UHead> |
152 | _GLIBCXX20_CONSTEXPR |
153 | _Head_base(__uses_alloc0, _UHead&& __uhead) |
154 | : _M_head_impl(std::forward<_UHead>(__uhead)) { } |
155 | |
156 | template<typename _Alloc, typename _UHead> |
157 | _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) |
158 | : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) |
159 | { } |
160 | |
161 | template<typename _Alloc, typename _UHead> |
162 | _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) |
163 | : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } |
164 | |
165 | static constexpr _Head& |
166 | _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } |
167 | |
168 | static constexpr const _Head& |
169 | _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } |
170 | |
171 | _Head _M_head_impl; |
172 | }; |
173 | |
174 | /** |
175 | * Contains the actual implementation of the @c tuple template, stored |
176 | * as a recursive inheritance hierarchy from the first element (most |
177 | * derived class) to the last (least derived class). The @c Idx |
178 | * parameter gives the 0-based index of the element stored at this |
179 | * point in the hierarchy; we use it to implement a constant-time |
180 | * get() operation. |
181 | */ |
182 | template<std::size_t _Idx, typename... _Elements> |
183 | struct _Tuple_impl; |
184 | |
185 | /** |
186 | * Recursive tuple implementation. Here we store the @c Head element |
187 | * and derive from a @c Tuple_impl containing the remaining elements |
188 | * (which contains the @c Tail). |
189 | */ |
190 | template<std::size_t _Idx, typename _Head, typename... _Tail> |
191 | struct _Tuple_impl<_Idx, _Head, _Tail...> |
192 | : public _Tuple_impl<_Idx + 1, _Tail...>, |
193 | private _Head_base<_Idx, _Head> |
194 | { |
195 | template<std::size_t, typename...> friend class _Tuple_impl; |
196 | |
197 | typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; |
198 | typedef _Head_base<_Idx, _Head> _Base; |
199 | |
200 | static constexpr _Head& |
201 | _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } |
202 | |
203 | static constexpr const _Head& |
204 | _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } |
205 | |
206 | static constexpr _Inherited& |
207 | _M_tail(_Tuple_impl& __t) noexcept { return __t; } |
208 | |
209 | static constexpr const _Inherited& |
210 | _M_tail(const _Tuple_impl& __t) noexcept { return __t; } |
211 | |
212 | constexpr _Tuple_impl() |
213 | : _Inherited(), _Base() { } |
214 | |
215 | explicit |
216 | constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) |
217 | : _Inherited(__tail...), _Base(__head) { } |
218 | |
219 | template<typename _UHead, typename... _UTail, typename = typename |
220 | enable_if<sizeof...(_Tail) == sizeof...(_UTail)>::type> |
221 | explicit |
222 | constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) |
223 | : _Inherited(std::forward<_UTail>(__tail)...), |
224 | _Base(std::forward<_UHead>(__head)) { } |
225 | |
226 | constexpr _Tuple_impl(const _Tuple_impl&) = default; |
227 | |
228 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
229 | // 2729. Missing SFINAE on std::pair::operator= |
230 | _Tuple_impl& operator=(const _Tuple_impl&) = delete; |
231 | |
232 | constexpr |
233 | _Tuple_impl(_Tuple_impl&& __in) |
234 | noexcept(__and_<is_nothrow_move_constructible<_Head>, |
235 | is_nothrow_move_constructible<_Inherited>>::value) |
236 | : _Inherited(std::move(_M_tail(__in))), |
237 | _Base(std::forward<_Head>(_M_head(__in))) { } |
238 | |
239 | template<typename... _UElements> |
240 | constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) |
241 | : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), |
242 | _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } |
243 | |
244 | template<typename _UHead, typename... _UTails> |
245 | constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) |
246 | : _Inherited(std::move |
247 | (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), |
248 | _Base(std::forward<_UHead> |
249 | (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } |
250 | |
251 | template<typename _Alloc> |
252 | _GLIBCXX20_CONSTEXPR |
253 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) |
254 | : _Inherited(__tag, __a), |
255 | _Base(__tag, __use_alloc<_Head>(__a)) { } |
256 | |
257 | template<typename _Alloc> |
258 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
259 | const _Head& __head, const _Tail&... __tail) |
260 | : _Inherited(__tag, __a, __tail...), |
261 | _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } |
262 | |
263 | template<typename _Alloc, typename _UHead, typename... _UTail, |
264 | typename = typename enable_if<sizeof...(_Tail) |
265 | == sizeof...(_UTail)>::type> |
266 | _GLIBCXX20_CONSTEXPR |
267 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
268 | _UHead&& __head, _UTail&&... __tail) |
269 | : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), |
270 | _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), |
271 | std::forward<_UHead>(__head)) { } |
272 | |
273 | template<typename _Alloc> |
274 | _GLIBCXX20_CONSTEXPR |
275 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
276 | const _Tuple_impl& __in) |
277 | : _Inherited(__tag, __a, _M_tail(__in)), |
278 | _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } |
279 | |
280 | template<typename _Alloc> |
281 | _GLIBCXX20_CONSTEXPR |
282 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
283 | _Tuple_impl&& __in) |
284 | : _Inherited(__tag, __a, std::move(_M_tail(__in))), |
285 | _Base(__use_alloc<_Head, _Alloc, _Head>(__a), |
286 | std::forward<_Head>(_M_head(__in))) { } |
287 | |
288 | template<typename _Alloc, typename... _UElements> |
289 | _GLIBCXX20_CONSTEXPR |
290 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
291 | const _Tuple_impl<_Idx, _UElements...>& __in) |
292 | : _Inherited(__tag, __a, |
293 | _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), |
294 | _Base(__use_alloc<_Head, _Alloc, _Head>(__a), |
295 | _Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } |
296 | |
297 | template<typename _Alloc, typename _UHead, typename... _UTails> |
298 | _GLIBCXX20_CONSTEXPR |
299 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
300 | _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) |
301 | : _Inherited(__tag, __a, std::move |
302 | (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), |
303 | _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), |
304 | std::forward<_UHead> |
305 | (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } |
306 | |
307 | template<typename... _UElements> |
308 | _GLIBCXX20_CONSTEXPR |
309 | void |
310 | _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) |
311 | { |
312 | _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); |
313 | _M_tail(*this)._M_assign( |
314 | _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); |
315 | } |
316 | |
317 | template<typename _UHead, typename... _UTails> |
318 | _GLIBCXX20_CONSTEXPR |
319 | void |
320 | _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) |
321 | { |
322 | _M_head(*this) = std::forward<_UHead> |
323 | (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); |
324 | _M_tail(*this)._M_assign( |
325 | std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); |
326 | } |
327 | |
328 | protected: |
329 | _GLIBCXX20_CONSTEXPR |
330 | void |
331 | _M_swap(_Tuple_impl& __in) |
332 | { |
333 | using std::swap; |
334 | swap(_M_head(*this), _M_head(__in)); |
335 | _Inherited::_M_swap(_M_tail(__in)); |
336 | } |
337 | }; |
338 | |
339 | // Basis case of inheritance recursion. |
340 | template<std::size_t _Idx, typename _Head> |
341 | struct _Tuple_impl<_Idx, _Head> |
342 | : private _Head_base<_Idx, _Head> |
343 | { |
344 | template<std::size_t, typename...> friend class _Tuple_impl; |
345 | |
346 | typedef _Head_base<_Idx, _Head> _Base; |
347 | |
348 | static constexpr _Head& |
349 | _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } |
350 | |
351 | static constexpr const _Head& |
352 | _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } |
353 | |
354 | constexpr _Tuple_impl() |
355 | : _Base() { } |
356 | |
357 | explicit |
358 | constexpr _Tuple_impl(const _Head& __head) |
359 | : _Base(__head) { } |
360 | |
361 | template<typename _UHead> |
362 | explicit |
363 | constexpr _Tuple_impl(_UHead&& __head) |
364 | : _Base(std::forward<_UHead>(__head)) { } |
365 | |
366 | constexpr _Tuple_impl(const _Tuple_impl&) = default; |
367 | |
368 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
369 | // 2729. Missing SFINAE on std::pair::operator= |
370 | _Tuple_impl& operator=(const _Tuple_impl&) = delete; |
371 | |
372 | constexpr |
373 | _Tuple_impl(_Tuple_impl&& __in) |
374 | noexcept(is_nothrow_move_constructible<_Head>::value) |
375 | : _Base(std::forward<_Head>(_M_head(__in))) { } |
376 | |
377 | template<typename _UHead> |
378 | constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) |
379 | : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } |
380 | |
381 | template<typename _UHead> |
382 | constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) |
383 | : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) |
384 | { } |
385 | |
386 | template<typename _Alloc> |
387 | _GLIBCXX20_CONSTEXPR |
388 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) |
389 | : _Base(__tag, __use_alloc<_Head>(__a)) { } |
390 | |
391 | template<typename _Alloc> |
392 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
393 | const _Head& __head) |
394 | : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } |
395 | |
396 | template<typename _Alloc, typename _UHead> |
397 | _GLIBCXX20_CONSTEXPR |
398 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
399 | _UHead&& __head) |
400 | : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), |
401 | std::forward<_UHead>(__head)) { } |
402 | |
403 | template<typename _Alloc> |
404 | _GLIBCXX20_CONSTEXPR |
405 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
406 | const _Tuple_impl& __in) |
407 | : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } |
408 | |
409 | template<typename _Alloc> |
410 | _GLIBCXX20_CONSTEXPR |
411 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
412 | _Tuple_impl&& __in) |
413 | : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), |
414 | std::forward<_Head>(_M_head(__in))) { } |
415 | |
416 | template<typename _Alloc, typename _UHead> |
417 | _GLIBCXX20_CONSTEXPR |
418 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
419 | const _Tuple_impl<_Idx, _UHead>& __in) |
420 | : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), |
421 | _Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } |
422 | |
423 | template<typename _Alloc, typename _UHead> |
424 | _GLIBCXX20_CONSTEXPR |
425 | _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, |
426 | _Tuple_impl<_Idx, _UHead>&& __in) |
427 | : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), |
428 | std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) |
429 | { } |
430 | |
431 | template<typename _UHead> |
432 | _GLIBCXX20_CONSTEXPR |
433 | void |
434 | _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) |
435 | { |
436 | _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); |
437 | } |
438 | |
439 | template<typename _UHead> |
440 | _GLIBCXX20_CONSTEXPR |
441 | void |
442 | _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) |
443 | { |
444 | _M_head(*this) |
445 | = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); |
446 | } |
447 | |
448 | protected: |
449 | _GLIBCXX20_CONSTEXPR |
450 | void |
451 | _M_swap(_Tuple_impl& __in) |
452 | { |
453 | using std::swap; |
454 | swap(_M_head(*this), _M_head(__in)); |
455 | } |
456 | }; |
457 | |
458 | // Concept utility functions, reused in conditionally-explicit |
459 | // constructors. |
460 | template<bool, typename... _Types> |
461 | struct _TupleConstraints |
462 | { |
463 | // Constraint for a non-explicit constructor. |
464 | // True iff each Ti in _Types... can be constructed from Ui in _UTypes... |
465 | // and every Ui is implicitly convertible to Ti. |
466 | template<typename... _UTypes> |
467 | static constexpr bool __is_implicitly_constructible() |
468 | { |
469 | return __and_<is_constructible<_Types, _UTypes>..., |
470 | is_convertible<_UTypes, _Types>... |
471 | >::value; |
472 | } |
473 | |
474 | // Constraint for a non-explicit constructor. |
475 | // True iff each Ti in _Types... can be constructed from Ui in _UTypes... |
476 | // but not every Ui is implicitly convertible to Ti. |
477 | template<typename... _UTypes> |
478 | static constexpr bool __is_explicitly_constructible() |
479 | { |
480 | return __and_<is_constructible<_Types, _UTypes>..., |
481 | __not_<__and_<is_convertible<_UTypes, _Types>...>> |
482 | >::value; |
483 | } |
484 | |
485 | static constexpr bool __is_implicitly_default_constructible() |
486 | { |
487 | return __and_<std::__is_implicitly_default_constructible<_Types>... |
488 | >::value; |
489 | } |
490 | |
491 | static constexpr bool __is_explicitly_default_constructible() |
492 | { |
493 | return __and_<is_default_constructible<_Types>..., |
494 | __not_<__and_< |
495 | std::__is_implicitly_default_constructible<_Types>...> |
496 | >>::value; |
497 | } |
498 | }; |
499 | |
500 | // Partial specialization used when a required precondition isn't met, |
501 | // e.g. when sizeof...(_Types) != sizeof...(_UTypes). |
502 | template<typename... _Types> |
503 | struct _TupleConstraints<false, _Types...> |
504 | { |
505 | template<typename... _UTypes> |
506 | static constexpr bool __is_implicitly_constructible() |
507 | { return false; } |
508 | |
509 | template<typename... _UTypes> |
510 | static constexpr bool __is_explicitly_constructible() |
511 | { return false; } |
512 | }; |
513 | |
514 | /// Primary class template, tuple |
515 | template<typename... _Elements> |
516 | class tuple : public _Tuple_impl<0, _Elements...> |
517 | { |
518 | typedef _Tuple_impl<0, _Elements...> _Inherited; |
519 | |
520 | template<bool _Cond> |
521 | using _TCC = _TupleConstraints<_Cond, _Elements...>; |
522 | |
523 | // Constraint for non-explicit default constructor |
524 | template<bool _Dummy> |
525 | using _ImplicitDefaultCtor = __enable_if_t< |
526 | _TCC<_Dummy>::__is_implicitly_default_constructible(), |
527 | bool>; |
528 | |
529 | // Constraint for explicit default constructor |
530 | template<bool _Dummy> |
531 | using _ExplicitDefaultCtor = __enable_if_t< |
532 | _TCC<_Dummy>::__is_explicitly_default_constructible(), |
533 | bool>; |
534 | |
535 | // Constraint for non-explicit constructors |
536 | template<bool _Cond, typename... _Args> |
537 | using _ImplicitCtor = __enable_if_t< |
538 | _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(), |
539 | bool>; |
540 | |
541 | // Constraint for non-explicit constructors |
542 | template<bool _Cond, typename... _Args> |
543 | using _ExplicitCtor = __enable_if_t< |
544 | _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(), |
545 | bool>; |
546 | |
547 | template<typename... _UElements> |
548 | static constexpr |
549 | __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool> |
550 | __assignable() |
551 | { return __and_<is_assignable<_Elements&, _UElements>...>::value; } |
552 | |
553 | // Condition for noexcept-specifier of an assignment operator. |
554 | template<typename... _UElements> |
555 | static constexpr bool __nothrow_assignable() |
556 | { |
557 | return |
558 | __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value; |
559 | } |
560 | |
561 | // Condition for noexcept-specifier of a constructor. |
562 | template<typename... _UElements> |
563 | static constexpr bool __nothrow_constructible() |
564 | { |
565 | return |
566 | __and_<is_nothrow_constructible<_Elements, _UElements>...>::value; |
567 | } |
568 | |
569 | // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1. |
570 | template<typename _Up> |
571 | static constexpr bool __valid_args() |
572 | { |
573 | return sizeof...(_Elements) == 1 |
574 | && !is_same<tuple, __remove_cvref_t<_Up>>::value; |
575 | } |
576 | |
577 | // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1. |
578 | template<typename, typename, typename... _Tail> |
579 | static constexpr bool __valid_args() |
580 | { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); } |
581 | |
582 | /* Constraint for constructors with a tuple<UTypes...> parameter ensures |
583 | * that the constructor is only viable when it would not interfere with |
584 | * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&). |
585 | * Such constructors are only viable if: |
586 | * either sizeof...(Types) != 1, |
587 | * or (when Types... expands to T and UTypes... expands to U) |
588 | * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>, |
589 | * and is_same_v<T, U> are all false. |
590 | */ |
591 | template<typename _Tuple, typename = tuple, |
592 | typename = __remove_cvref_t<_Tuple>> |
593 | struct _UseOtherCtor |
594 | : false_type |
595 | { }; |
596 | // If TUPLE is convertible to the single element in *this, |
597 | // then TUPLE should match tuple(UTypes&&...) instead. |
598 | template<typename _Tuple, typename _Tp, typename _Up> |
599 | struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> |
600 | : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>> |
601 | { }; |
602 | // If TUPLE and *this each have a single element of the same type, |
603 | // then TUPLE should match a copy/move constructor instead. |
604 | template<typename _Tuple, typename _Tp> |
605 | struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>> |
606 | : true_type |
607 | { }; |
608 | |
609 | // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1 |
610 | // and the single element in Types can be initialized from TUPLE, |
611 | // or is the same type as tuple_element_t<0, TUPLE>. |
612 | template<typename _Tuple> |
613 | static constexpr bool __use_other_ctor() |
614 | { return _UseOtherCtor<_Tuple>::value; } |
615 | |
616 | public: |
617 | template<typename _Dummy = void, |
618 | _ImplicitDefaultCtor<is_void<_Dummy>::value> = true> |
619 | constexpr |
620 | tuple() |
621 | noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value) |
622 | : _Inherited() { } |
623 | |
624 | template<typename _Dummy = void, |
625 | _ExplicitDefaultCtor<is_void<_Dummy>::value> = false> |
626 | explicit constexpr |
627 | tuple() |
628 | noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value) |
629 | : _Inherited() { } |
630 | |
631 | template<bool _NotEmpty = (sizeof...(_Elements) >= 1), |
632 | _ImplicitCtor<_NotEmpty, const _Elements&...> = true> |
633 | constexpr |
634 | tuple(const _Elements&... __elements) |
635 | noexcept(__nothrow_constructible<const _Elements&...>()) |
636 | : _Inherited(__elements...) { } |
637 | |
638 | template<bool _NotEmpty = (sizeof...(_Elements) >= 1), |
639 | _ExplicitCtor<_NotEmpty, const _Elements&...> = false> |
640 | explicit constexpr |
641 | tuple(const _Elements&... __elements) |
642 | noexcept(__nothrow_constructible<const _Elements&...>()) |
643 | : _Inherited(__elements...) { } |
644 | |
645 | template<typename... _UElements, |
646 | bool _Valid = __valid_args<_UElements...>(), |
647 | _ImplicitCtor<_Valid, _UElements...> = true> |
648 | constexpr |
649 | tuple(_UElements&&... __elements) |
650 | noexcept(__nothrow_constructible<_UElements...>()) |
651 | : _Inherited(std::forward<_UElements>(__elements)...) { } |
652 | |
653 | template<typename... _UElements, |
654 | bool _Valid = __valid_args<_UElements...>(), |
655 | _ExplicitCtor<_Valid, _UElements...> = false> |
656 | explicit constexpr |
657 | tuple(_UElements&&... __elements) |
658 | noexcept(__nothrow_constructible<_UElements...>()) |
659 | : _Inherited(std::forward<_UElements>(__elements)...) { } |
660 | |
661 | constexpr tuple(const tuple&) = default; |
662 | |
663 | constexpr tuple(tuple&&) = default; |
664 | |
665 | template<typename... _UElements, |
666 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
667 | && !__use_other_ctor<const tuple<_UElements...>&>(), |
668 | _ImplicitCtor<_Valid, const _UElements&...> = true> |
669 | constexpr |
670 | tuple(const tuple<_UElements...>& __in) |
671 | noexcept(__nothrow_constructible<const _UElements&...>()) |
672 | : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) |
673 | { } |
674 | |
675 | template<typename... _UElements, |
676 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
677 | && !__use_other_ctor<const tuple<_UElements...>&>(), |
678 | _ExplicitCtor<_Valid, const _UElements&...> = false> |
679 | explicit constexpr |
680 | tuple(const tuple<_UElements...>& __in) |
681 | noexcept(__nothrow_constructible<const _UElements&...>()) |
682 | : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) |
683 | { } |
684 | |
685 | template<typename... _UElements, |
686 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
687 | && !__use_other_ctor<tuple<_UElements...>&&>(), |
688 | _ImplicitCtor<_Valid, _UElements...> = true> |
689 | constexpr |
690 | tuple(tuple<_UElements...>&& __in) |
691 | noexcept(__nothrow_constructible<_UElements...>()) |
692 | : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } |
693 | |
694 | template<typename... _UElements, |
695 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
696 | && !__use_other_ctor<tuple<_UElements...>&&>(), |
697 | _ExplicitCtor<_Valid, _UElements...> = false> |
698 | explicit constexpr |
699 | tuple(tuple<_UElements...>&& __in) |
700 | noexcept(__nothrow_constructible<_UElements...>()) |
701 | : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } |
702 | |
703 | // Allocator-extended constructors. |
704 | |
705 | template<typename _Alloc, |
706 | _ImplicitDefaultCtor<is_object<_Alloc>::value> = true> |
707 | _GLIBCXX20_CONSTEXPR |
708 | tuple(allocator_arg_t __tag, const _Alloc& __a) |
709 | : _Inherited(__tag, __a) { } |
710 | |
711 | template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1), |
712 | _ImplicitCtor<_NotEmpty, const _Elements&...> = true> |
713 | _GLIBCXX20_CONSTEXPR |
714 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
715 | const _Elements&... __elements) |
716 | : _Inherited(__tag, __a, __elements...) { } |
717 | |
718 | template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1), |
719 | _ExplicitCtor<_NotEmpty, const _Elements&...> = false> |
720 | _GLIBCXX20_CONSTEXPR |
721 | explicit |
722 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
723 | const _Elements&... __elements) |
724 | : _Inherited(__tag, __a, __elements...) { } |
725 | |
726 | template<typename _Alloc, typename... _UElements, |
727 | bool _Valid = __valid_args<_UElements...>(), |
728 | _ImplicitCtor<_Valid, _UElements...> = true> |
729 | _GLIBCXX20_CONSTEXPR |
730 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
731 | _UElements&&... __elements) |
732 | : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) |
733 | { } |
734 | |
735 | template<typename _Alloc, typename... _UElements, |
736 | bool _Valid = __valid_args<_UElements...>(), |
737 | _ExplicitCtor<_Valid, _UElements...> = false> |
738 | _GLIBCXX20_CONSTEXPR |
739 | explicit |
740 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
741 | _UElements&&... __elements) |
742 | : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) |
743 | { } |
744 | |
745 | template<typename _Alloc> |
746 | _GLIBCXX20_CONSTEXPR |
747 | tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) |
748 | : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { } |
749 | |
750 | template<typename _Alloc> |
751 | _GLIBCXX20_CONSTEXPR |
752 | tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) |
753 | : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } |
754 | |
755 | template<typename _Alloc, typename... _UElements, |
756 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
757 | && !__use_other_ctor<const tuple<_UElements...>&>(), |
758 | _ImplicitCtor<_Valid, const _UElements&...> = true> |
759 | _GLIBCXX20_CONSTEXPR |
760 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
761 | const tuple<_UElements...>& __in) |
762 | : _Inherited(__tag, __a, |
763 | static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) |
764 | { } |
765 | |
766 | template<typename _Alloc, typename... _UElements, |
767 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
768 | && !__use_other_ctor<const tuple<_UElements...>&>(), |
769 | _ExplicitCtor<_Valid, const _UElements&...> = false> |
770 | _GLIBCXX20_CONSTEXPR |
771 | explicit |
772 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
773 | const tuple<_UElements...>& __in) |
774 | : _Inherited(__tag, __a, |
775 | static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) |
776 | { } |
777 | |
778 | template<typename _Alloc, typename... _UElements, |
779 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
780 | && !__use_other_ctor<tuple<_UElements...>&&>(), |
781 | _ImplicitCtor<_Valid, _UElements...> = true> |
782 | _GLIBCXX20_CONSTEXPR |
783 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
784 | tuple<_UElements...>&& __in) |
785 | : _Inherited(__tag, __a, |
786 | static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) |
787 | { } |
788 | |
789 | template<typename _Alloc, typename... _UElements, |
790 | bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) |
791 | && !__use_other_ctor<tuple<_UElements...>&&>(), |
792 | _ExplicitCtor<_Valid, _UElements...> = false> |
793 | _GLIBCXX20_CONSTEXPR |
794 | explicit |
795 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
796 | tuple<_UElements...>&& __in) |
797 | : _Inherited(__tag, __a, |
798 | static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) |
799 | { } |
800 | |
801 | // tuple assignment |
802 | |
803 | _GLIBCXX20_CONSTEXPR |
804 | tuple& |
805 | operator=(typename conditional<__assignable<const _Elements&...>(), |
806 | const tuple&, |
807 | const __nonesuch&>::type __in) |
808 | noexcept(__nothrow_assignable<const _Elements&...>()) |
809 | { |
810 | this->_M_assign(__in); |
811 | return *this; |
812 | } |
813 | |
814 | _GLIBCXX20_CONSTEXPR |
815 | tuple& |
816 | operator=(typename conditional<__assignable<_Elements...>(), |
817 | tuple&&, |
818 | __nonesuch&&>::type __in) |
819 | noexcept(__nothrow_assignable<_Elements...>()) |
820 | { |
821 | this->_M_assign(std::move(__in)); |
822 | return *this; |
823 | } |
824 | |
825 | template<typename... _UElements> |
826 | _GLIBCXX20_CONSTEXPR |
827 | __enable_if_t<__assignable<const _UElements&...>(), tuple&> |
828 | operator=(const tuple<_UElements...>& __in) |
829 | noexcept(__nothrow_assignable<const _UElements&...>()) |
830 | { |
831 | this->_M_assign(__in); |
832 | return *this; |
833 | } |
834 | |
835 | template<typename... _UElements> |
836 | _GLIBCXX20_CONSTEXPR |
837 | __enable_if_t<__assignable<_UElements...>(), tuple&> |
838 | operator=(tuple<_UElements...>&& __in) |
839 | noexcept(__nothrow_assignable<_UElements...>()) |
840 | { |
841 | this->_M_assign(std::move(__in)); |
842 | return *this; |
843 | } |
844 | |
845 | // tuple swap |
846 | _GLIBCXX20_CONSTEXPR |
847 | void |
848 | swap(tuple& __in) |
849 | noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value) |
850 | { _Inherited::_M_swap(__in); } |
851 | }; |
852 | |
853 | #if __cpp_deduction_guides201703L >= 201606 |
854 | template<typename... _UTypes> |
855 | tuple(_UTypes...) -> tuple<_UTypes...>; |
856 | template<typename _T1, typename _T2> |
857 | tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>; |
858 | template<typename _Alloc, typename... _UTypes> |
859 | tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>; |
860 | template<typename _Alloc, typename _T1, typename _T2> |
861 | tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>; |
862 | template<typename _Alloc, typename... _UTypes> |
863 | tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>; |
864 | #endif |
865 | |
866 | // Explicit specialization, zero-element tuple. |
867 | template<> |
868 | class tuple<> |
869 | { |
870 | public: |
871 | void swap(tuple&) noexcept { /* no-op */ } |
872 | // We need the default since we're going to define no-op |
873 | // allocator constructors. |
874 | tuple() = default; |
875 | // No-op allocator constructors. |
876 | template<typename _Alloc> |
877 | _GLIBCXX20_CONSTEXPR |
878 | tuple(allocator_arg_t, const _Alloc&) noexcept { } |
879 | template<typename _Alloc> |
880 | _GLIBCXX20_CONSTEXPR |
881 | tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { } |
882 | }; |
883 | |
884 | /// Partial specialization, 2-element tuple. |
885 | /// Includes construction and assignment from a pair. |
886 | template<typename _T1, typename _T2> |
887 | class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> |
888 | { |
889 | typedef _Tuple_impl<0, _T1, _T2> _Inherited; |
890 | |
891 | // Constraint for non-explicit default constructor |
892 | template<bool _Dummy, typename _U1, typename _U2> |
893 | using _ImplicitDefaultCtor = __enable_if_t< |
894 | _TupleConstraints<_Dummy, _U1, _U2>:: |
895 | __is_implicitly_default_constructible(), |
896 | bool>; |
897 | |
898 | // Constraint for explicit default constructor |
899 | template<bool _Dummy, typename _U1, typename _U2> |
900 | using _ExplicitDefaultCtor = __enable_if_t< |
901 | _TupleConstraints<_Dummy, _U1, _U2>:: |
902 | __is_explicitly_default_constructible(), |
903 | bool>; |
904 | |
905 | template<bool _Dummy> |
906 | using _TCC = _TupleConstraints<_Dummy, _T1, _T2>; |
907 | |
908 | // Constraint for non-explicit constructors |
909 | template<bool _Cond, typename _U1, typename _U2> |
910 | using _ImplicitCtor = __enable_if_t< |
911 | _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(), |
912 | bool>; |
913 | |
914 | // Constraint for non-explicit constructors |
915 | template<bool _Cond, typename _U1, typename _U2> |
916 | using _ExplicitCtor = __enable_if_t< |
917 | _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(), |
918 | bool>; |
919 | |
920 | template<typename _U1, typename _U2> |
921 | static constexpr bool __assignable() |
922 | { |
923 | return __and_<is_assignable<_T1&, _U1>, |
924 | is_assignable<_T2&, _U2>>::value; |
925 | } |
926 | |
927 | template<typename _U1, typename _U2> |
928 | static constexpr bool __nothrow_assignable() |
929 | { |
930 | return __and_<is_nothrow_assignable<_T1&, _U1>, |
931 | is_nothrow_assignable<_T2&, _U2>>::value; |
932 | } |
933 | |
934 | template<typename _U1, typename _U2> |
935 | static constexpr bool __nothrow_constructible() |
936 | { |
937 | return __and_<is_nothrow_constructible<_T1, _U1>, |
938 | is_nothrow_constructible<_T2, _U2>>::value; |
939 | } |
940 | |
941 | static constexpr bool __nothrow_default_constructible() |
942 | { |
943 | return __and_<is_nothrow_default_constructible<_T1>, |
944 | is_nothrow_default_constructible<_T2>>::value; |
945 | } |
946 | |
947 | template<typename _U1> |
948 | static constexpr bool __is_alloc_arg() |
949 | { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; } |
950 | |
951 | public: |
952 | template<bool _Dummy = true, |
953 | _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true> |
954 | constexpr |
955 | tuple() |
956 | noexcept(__nothrow_default_constructible()) |
957 | : _Inherited() { } |
958 | |
959 | template<bool _Dummy = true, |
960 | _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false> |
961 | explicit constexpr |
962 | tuple() |
963 | noexcept(__nothrow_default_constructible()) |
964 | : _Inherited() { } |
965 | |
966 | template<bool _Dummy = true, |
967 | _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true> |
968 | constexpr |
969 | tuple(const _T1& __a1, const _T2& __a2) |
970 | noexcept(__nothrow_constructible<const _T1&, const _T2&>()) |
971 | : _Inherited(__a1, __a2) { } |
972 | |
973 | template<bool _Dummy = true, |
974 | _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false> |
975 | explicit constexpr |
976 | tuple(const _T1& __a1, const _T2& __a2) |
977 | noexcept(__nothrow_constructible<const _T1&, const _T2&>()) |
978 | : _Inherited(__a1, __a2) { } |
979 | |
980 | template<typename _U1, typename _U2, |
981 | _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true> |
982 | constexpr |
983 | tuple(_U1&& __a1, _U2&& __a2) |
984 | noexcept(__nothrow_constructible<_U1, _U2>()) |
985 | : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } |
986 | |
987 | template<typename _U1, typename _U2, |
988 | _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false> |
989 | explicit constexpr |
990 | tuple(_U1&& __a1, _U2&& __a2) |
991 | noexcept(__nothrow_constructible<_U1, _U2>()) |
992 | : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } |
993 | |
994 | constexpr tuple(const tuple&) = default; |
995 | |
996 | constexpr tuple(tuple&&) = default; |
997 | |
998 | template<typename _U1, typename _U2, |
999 | _ImplicitCtor<true, const _U1&, const _U2&> = true> |
1000 | constexpr |
1001 | tuple(const tuple<_U1, _U2>& __in) |
1002 | noexcept(__nothrow_constructible<const _U1&, const _U2&>()) |
1003 | : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { } |
1004 | |
1005 | template<typename _U1, typename _U2, |
1006 | _ExplicitCtor<true, const _U1&, const _U2&> = false> |
1007 | explicit constexpr |
1008 | tuple(const tuple<_U1, _U2>& __in) |
1009 | noexcept(__nothrow_constructible<const _U1&, const _U2&>()) |
1010 | : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { } |
1011 | |
1012 | template<typename _U1, typename _U2, |
1013 | _ImplicitCtor<true, _U1, _U2> = true> |
1014 | constexpr |
1015 | tuple(tuple<_U1, _U2>&& __in) |
1016 | noexcept(__nothrow_constructible<_U1, _U2>()) |
1017 | : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } |
1018 | |
1019 | template<typename _U1, typename _U2, |
1020 | _ExplicitCtor<true, _U1, _U2> = false> |
1021 | explicit constexpr |
1022 | tuple(tuple<_U1, _U2>&& __in) |
1023 | noexcept(__nothrow_constructible<_U1, _U2>()) |
1024 | : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } |
1025 | |
1026 | template<typename _U1, typename _U2, |
1027 | _ImplicitCtor<true, const _U1&, const _U2&> = true> |
1028 | constexpr |
1029 | tuple(const pair<_U1, _U2>& __in) |
1030 | noexcept(__nothrow_constructible<const _U1&, const _U2&>()) |
1031 | : _Inherited(__in.first, __in.second) { } |
1032 | |
1033 | template<typename _U1, typename _U2, |
1034 | _ExplicitCtor<true, const _U1&, const _U2&> = false> |
1035 | explicit constexpr |
1036 | tuple(const pair<_U1, _U2>& __in) |
1037 | noexcept(__nothrow_constructible<const _U1&, const _U2&>()) |
1038 | : _Inherited(__in.first, __in.second) { } |
1039 | |
1040 | template<typename _U1, typename _U2, |
1041 | _ImplicitCtor<true, _U1, _U2> = true> |
1042 | constexpr |
1043 | tuple(pair<_U1, _U2>&& __in) |
1044 | noexcept(__nothrow_constructible<_U1, _U2>()) |
1045 | : _Inherited(std::forward<_U1>(__in.first), |
1046 | std::forward<_U2>(__in.second)) { } |
1047 | |
1048 | template<typename _U1, typename _U2, |
1049 | _ExplicitCtor<true, _U1, _U2> = false> |
1050 | explicit constexpr |
1051 | tuple(pair<_U1, _U2>&& __in) |
1052 | noexcept(__nothrow_constructible<_U1, _U2>()) |
1053 | : _Inherited(std::forward<_U1>(__in.first), |
1054 | std::forward<_U2>(__in.second)) { } |
1055 | |
1056 | // Allocator-extended constructors. |
1057 | |
1058 | template<typename _Alloc, |
1059 | _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true> |
1060 | _GLIBCXX20_CONSTEXPR |
1061 | tuple(allocator_arg_t __tag, const _Alloc& __a) |
1062 | : _Inherited(__tag, __a) { } |
1063 | |
1064 | template<typename _Alloc, bool _Dummy = true, |
1065 | _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true> |
1066 | _GLIBCXX20_CONSTEXPR |
1067 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
1068 | const _T1& __a1, const _T2& __a2) |
1069 | : _Inherited(__tag, __a, __a1, __a2) { } |
1070 | |
1071 | template<typename _Alloc, bool _Dummy = true, |
1072 | _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false> |
1073 | explicit |
1074 | _GLIBCXX20_CONSTEXPR |
1075 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
1076 | const _T1& __a1, const _T2& __a2) |
1077 | : _Inherited(__tag, __a, __a1, __a2) { } |
1078 | |
1079 | template<typename _Alloc, typename _U1, typename _U2, |
1080 | _ImplicitCtor<true, _U1, _U2> = true> |
1081 | _GLIBCXX20_CONSTEXPR |
1082 | tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) |
1083 | : _Inherited(__tag, __a, std::forward<_U1>(__a1), |
1084 | std::forward<_U2>(__a2)) { } |
1085 | |
1086 | template<typename _Alloc, typename _U1, typename _U2, |
1087 | _ExplicitCtor<true, _U1, _U2> = false> |
1088 | explicit |
1089 | _GLIBCXX20_CONSTEXPR |
1090 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
1091 | _U1&& __a1, _U2&& __a2) |
1092 | : _Inherited(__tag, __a, std::forward<_U1>(__a1), |
1093 | std::forward<_U2>(__a2)) { } |
1094 | |
1095 | template<typename _Alloc> |
1096 | _GLIBCXX20_CONSTEXPR |
1097 | tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) |
1098 | : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { } |
1099 | |
1100 | template<typename _Alloc> |
1101 | _GLIBCXX20_CONSTEXPR |
1102 | tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) |
1103 | : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } |
1104 | |
1105 | template<typename _Alloc, typename _U1, typename _U2, |
1106 | _ImplicitCtor<true, const _U1&, const _U2&> = true> |
1107 | _GLIBCXX20_CONSTEXPR |
1108 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
1109 | const tuple<_U1, _U2>& __in) |
1110 | : _Inherited(__tag, __a, |
1111 | static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) |
1112 | { } |
1113 | |
1114 | template<typename _Alloc, typename _U1, typename _U2, |
1115 | _ExplicitCtor<true, const _U1&, const _U2&> = false> |
1116 | explicit |
1117 | _GLIBCXX20_CONSTEXPR |
1118 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
1119 | const tuple<_U1, _U2>& __in) |
1120 | : _Inherited(__tag, __a, |
1121 | static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) |
1122 | { } |
1123 | |
1124 | template<typename _Alloc, typename _U1, typename _U2, |
1125 | _ImplicitCtor<true, _U1, _U2> = true> |
1126 | _GLIBCXX20_CONSTEXPR |
1127 | tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) |
1128 | : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) |
1129 | { } |
1130 | |
1131 | template<typename _Alloc, typename _U1, typename _U2, |
1132 | _ExplicitCtor<true, _U1, _U2> = false> |
1133 | explicit |
1134 | _GLIBCXX20_CONSTEXPR |
1135 | tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) |
1136 | : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) |
1137 | { } |
1138 | |
1139 | template<typename _Alloc, typename _U1, typename _U2, |
1140 | _ImplicitCtor<true, const _U1&, const _U2&> = true> |
1141 | _GLIBCXX20_CONSTEXPR |
1142 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
1143 | const pair<_U1, _U2>& __in) |
1144 | : _Inherited(__tag, __a, __in.first, __in.second) { } |
1145 | |
1146 | template<typename _Alloc, typename _U1, typename _U2, |
1147 | _ExplicitCtor<true, const _U1&, const _U2&> = false> |
1148 | explicit |
1149 | _GLIBCXX20_CONSTEXPR |
1150 | tuple(allocator_arg_t __tag, const _Alloc& __a, |
1151 | const pair<_U1, _U2>& __in) |
1152 | : _Inherited(__tag, __a, __in.first, __in.second) { } |
1153 | |
1154 | template<typename _Alloc, typename _U1, typename _U2, |
1155 | _ImplicitCtor<true, _U1, _U2> = true> |
1156 | _GLIBCXX20_CONSTEXPR |
1157 | tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) |
1158 | : _Inherited(__tag, __a, std::forward<_U1>(__in.first), |
1159 | std::forward<_U2>(__in.second)) { } |
1160 | |
1161 | template<typename _Alloc, typename _U1, typename _U2, |
1162 | _ExplicitCtor<true, _U1, _U2> = false> |
1163 | explicit |
1164 | _GLIBCXX20_CONSTEXPR |
1165 | tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) |
1166 | : _Inherited(__tag, __a, std::forward<_U1>(__in.first), |
1167 | std::forward<_U2>(__in.second)) { } |
1168 | |
1169 | // Tuple assignment. |
1170 | |
1171 | _GLIBCXX20_CONSTEXPR |
1172 | tuple& |
1173 | operator=(typename conditional<__assignable<const _T1&, const _T2&>(), |
1174 | const tuple&, |
1175 | const __nonesuch&>::type __in) |
1176 | noexcept(__nothrow_assignable<const _T1&, const _T2&>()) |
1177 | { |
1178 | this->_M_assign(__in); |
1179 | return *this; |
1180 | } |
1181 | |
1182 | _GLIBCXX20_CONSTEXPR |
1183 | tuple& |
1184 | operator=(typename conditional<__assignable<_T1, _T2>(), |
1185 | tuple&&, |
1186 | __nonesuch&&>::type __in) |
1187 | noexcept(__nothrow_assignable<_T1, _T2>()) |
1188 | { |
1189 | this->_M_assign(std::move(__in)); |
1190 | return *this; |
1191 | } |
1192 | |
1193 | template<typename _U1, typename _U2> |
1194 | _GLIBCXX20_CONSTEXPR |
1195 | __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&> |
1196 | operator=(const tuple<_U1, _U2>& __in) |
1197 | noexcept(__nothrow_assignable<const _U1&, const _U2&>()) |
1198 | { |
1199 | this->_M_assign(__in); |
1200 | return *this; |
1201 | } |
1202 | |
1203 | template<typename _U1, typename _U2> |
1204 | _GLIBCXX20_CONSTEXPR |
1205 | __enable_if_t<__assignable<_U1, _U2>(), tuple&> |
1206 | operator=(tuple<_U1, _U2>&& __in) |
1207 | noexcept(__nothrow_assignable<_U1, _U2>()) |
1208 | { |
1209 | this->_M_assign(std::move(__in)); |
1210 | return *this; |
1211 | } |
1212 | |
1213 | template<typename _U1, typename _U2> |
1214 | _GLIBCXX20_CONSTEXPR |
1215 | __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&> |
1216 | operator=(const pair<_U1, _U2>& __in) |
1217 | noexcept(__nothrow_assignable<const _U1&, const _U2&>()) |
1218 | { |
1219 | this->_M_head(*this) = __in.first; |
1220 | this->_M_tail(*this)._M_head(*this) = __in.second; |
1221 | return *this; |
1222 | } |
1223 | |
1224 | template<typename _U1, typename _U2> |
1225 | _GLIBCXX20_CONSTEXPR |
1226 | __enable_if_t<__assignable<_U1, _U2>(), tuple&> |
1227 | operator=(pair<_U1, _U2>&& __in) |
1228 | noexcept(__nothrow_assignable<_U1, _U2>()) |
1229 | { |
1230 | this->_M_head(*this) = std::forward<_U1>(__in.first); |
1231 | this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); |
1232 | return *this; |
1233 | } |
1234 | |
1235 | _GLIBCXX20_CONSTEXPR |
1236 | void |
1237 | swap(tuple& __in) |
1238 | noexcept(__and_<__is_nothrow_swappable<_T1>, |
1239 | __is_nothrow_swappable<_T2>>::value) |
1240 | { _Inherited::_M_swap(__in); } |
1241 | }; |
1242 | |
1243 | |
1244 | /// class tuple_size |
1245 | template<typename... _Elements> |
1246 | struct tuple_size<tuple<_Elements...>> |
1247 | : public integral_constant<std::size_t, sizeof...(_Elements)> { }; |
1248 | |
1249 | #if __cplusplus201703L > 201402L |
1250 | template <typename _Tp> |
1251 | inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; |
1252 | #endif |
1253 | |
1254 | /** |
1255 | * Recursive case for tuple_element: strip off the first element in |
1256 | * the tuple and retrieve the (i-1)th element of the remaining tuple. |
1257 | */ |
1258 | template<std::size_t __i, typename _Head, typename... _Tail> |
1259 | struct tuple_element<__i, tuple<_Head, _Tail...> > |
1260 | : tuple_element<__i - 1, tuple<_Tail...> > { }; |
1261 | |
1262 | /** |
1263 | * Basis case for tuple_element: The first element is the one we're seeking. |
1264 | */ |
1265 | template<typename _Head, typename... _Tail> |
1266 | struct tuple_element<0, tuple<_Head, _Tail...> > |
1267 | { |
1268 | typedef _Head type; |
1269 | }; |
1270 | |
1271 | /** |
1272 | * Error case for tuple_element: invalid index. |
1273 | */ |
1274 | template<size_t __i> |
1275 | struct tuple_element<__i, tuple<>> |
1276 | { |
1277 | static_assert(__i < tuple_size<tuple<>>::value, |
1278 | "tuple index is in range"); |
1279 | }; |
1280 | |
1281 | template<std::size_t __i, typename _Head, typename... _Tail> |
1282 | constexpr _Head& |
1283 | __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept |
1284 | { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } |
1285 | |
1286 | template<std::size_t __i, typename _Head, typename... _Tail> |
1287 | constexpr const _Head& |
1288 | __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept |
1289 | { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } |
1290 | |
1291 | /// Return a reference to the ith element of a tuple. |
1292 | template<std::size_t __i, typename... _Elements> |
1293 | constexpr __tuple_element_t<__i, tuple<_Elements...>>& |
1294 | get(tuple<_Elements...>& __t) noexcept |
1295 | { return std::__get_helper<__i>(__t); } |
1296 | |
1297 | /// Return a const reference to the ith element of a const tuple. |
1298 | template<std::size_t __i, typename... _Elements> |
1299 | constexpr const __tuple_element_t<__i, tuple<_Elements...>>& |
1300 | get(const tuple<_Elements...>& __t) noexcept |
1301 | { return std::__get_helper<__i>(__t); } |
1302 | |
1303 | /// Return an rvalue reference to the ith element of a tuple rvalue. |
1304 | template<std::size_t __i, typename... _Elements> |
1305 | constexpr __tuple_element_t<__i, tuple<_Elements...>>&& |
1306 | get(tuple<_Elements...>&& __t) noexcept |
1307 | { |
1308 | typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; |
1309 | return std::forward<__element_type&&>(std::get<__i>(__t)); |
1310 | } |
1311 | |
1312 | /// Return a const rvalue reference to the ith element of a const tuple rvalue. |
1313 | template<std::size_t __i, typename... _Elements> |
1314 | constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& |
1315 | get(const tuple<_Elements...>&& __t) noexcept |
1316 | { |
1317 | typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; |
1318 | return std::forward<const __element_type&&>(std::get<__i>(__t)); |
1319 | } |
1320 | |
1321 | #if __cplusplus201703L >= 201402L |
1322 | |
1323 | #define __cpp_lib_tuples_by_type201304 201304 |
1324 | |
1325 | template<typename _Head, size_t __i, typename... _Tail> |
1326 | constexpr _Head& |
1327 | __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept |
1328 | { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } |
1329 | |
1330 | template<typename _Head, size_t __i, typename... _Tail> |
1331 | constexpr const _Head& |
1332 | __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept |
1333 | { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } |
1334 | |
1335 | /// Return a reference to the unique element of type _Tp of a tuple. |
1336 | template <typename _Tp, typename... _Types> |
1337 | constexpr _Tp& |
1338 | get(tuple<_Types...>& __t) noexcept |
1339 | { return std::__get_helper2<_Tp>(__t); } |
1340 | |
1341 | /// Return a reference to the unique element of type _Tp of a tuple rvalue. |
1342 | template <typename _Tp, typename... _Types> |
1343 | constexpr _Tp&& |
1344 | get(tuple<_Types...>&& __t) noexcept |
1345 | { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } |
1346 | |
1347 | /// Return a const reference to the unique element of type _Tp of a tuple. |
1348 | template <typename _Tp, typename... _Types> |
1349 | constexpr const _Tp& |
1350 | get(const tuple<_Types...>& __t) noexcept |
1351 | { return std::__get_helper2<_Tp>(__t); } |
1352 | |
1353 | /// Return a const reference to the unique element of type _Tp of |
1354 | /// a const tuple rvalue. |
1355 | template <typename _Tp, typename... _Types> |
1356 | constexpr const _Tp&& |
1357 | get(const tuple<_Types...>&& __t) noexcept |
1358 | { return std::forward<const _Tp&&>(std::__get_helper2<_Tp>(__t)); } |
1359 | #endif |
1360 | |
1361 | // This class performs the comparison operations on tuples |
1362 | template<typename _Tp, typename _Up, size_t __i, size_t __size> |
1363 | struct __tuple_compare |
1364 | { |
1365 | static constexpr bool |
1366 | __eq(const _Tp& __t, const _Up& __u) |
1367 | { |
1368 | return bool(std::get<__i>(__t) == std::get<__i>(__u)) |
1369 | && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u); |
1370 | } |
1371 | |
1372 | static constexpr bool |
1373 | __less(const _Tp& __t, const _Up& __u) |
1374 | { |
1375 | return bool(std::get<__i>(__t) < std::get<__i>(__u)) |
1376 | || (!bool(std::get<__i>(__u) < std::get<__i>(__t)) |
1377 | && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u)); |
1378 | } |
1379 | }; |
1380 | |
1381 | template<typename _Tp, typename _Up, size_t __size> |
1382 | struct __tuple_compare<_Tp, _Up, __size, __size> |
1383 | { |
1384 | static constexpr bool |
1385 | __eq(const _Tp&, const _Up&) { return true; } |
1386 | |
1387 | static constexpr bool |
1388 | __less(const _Tp&, const _Up&) { return false; } |
1389 | }; |
1390 | |
1391 | template<typename... _TElements, typename... _UElements> |
1392 | constexpr bool |
1393 | operator==(const tuple<_TElements...>& __t, |
1394 | const tuple<_UElements...>& __u) |
1395 | { |
1396 | static_assert(sizeof...(_TElements) == sizeof...(_UElements), |
1397 | "tuple objects can only be compared if they have equal sizes."); |
1398 | using __compare = __tuple_compare<tuple<_TElements...>, |
1399 | tuple<_UElements...>, |
1400 | 0, sizeof...(_TElements)>; |
1401 | return __compare::__eq(__t, __u); |
1402 | } |
1403 | |
1404 | #if __cpp_lib_three_way_comparison |
1405 | template<typename _Cat, typename _Tp, typename _Up> |
1406 | constexpr _Cat |
1407 | __tuple_cmp(const _Tp&, const _Up&, index_sequence<>) |
1408 | { return _Cat::equivalent; } |
1409 | |
1410 | template<typename _Cat, typename _Tp, typename _Up, |
1411 | size_t _Idx0, size_t... _Idxs> |
1412 | constexpr _Cat |
1413 | __tuple_cmp(const _Tp& __t, const _Up& __u, |
1414 | index_sequence<_Idx0, _Idxs...>) |
1415 | { |
1416 | auto __c |
1417 | = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u)); |
1418 | if (__c != 0) |
1419 | return __c; |
1420 | return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>()); |
1421 | } |
1422 | |
1423 | template<typename... _Tps, typename... _Ups> |
1424 | constexpr |
1425 | common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...> |
1426 | operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u) |
1427 | { |
1428 | using _Cat |
1429 | = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>; |
1430 | return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>()); |
1431 | } |
1432 | #else |
1433 | template<typename... _TElements, typename... _UElements> |
1434 | constexpr bool |
1435 | operator<(const tuple<_TElements...>& __t, |
1436 | const tuple<_UElements...>& __u) |
1437 | { |
1438 | static_assert(sizeof...(_TElements) == sizeof...(_UElements), |
1439 | "tuple objects can only be compared if they have equal sizes."); |
1440 | using __compare = __tuple_compare<tuple<_TElements...>, |
1441 | tuple<_UElements...>, |
1442 | 0, sizeof...(_TElements)>; |
1443 | return __compare::__less(__t, __u); |
1444 | } |
1445 | |
1446 | template<typename... _TElements, typename... _UElements> |
1447 | constexpr bool |
1448 | operator!=(const tuple<_TElements...>& __t, |
1449 | const tuple<_UElements...>& __u) |
1450 | { return !(__t == __u); } |
1451 | |
1452 | template<typename... _TElements, typename... _UElements> |
1453 | constexpr bool |
1454 | operator>(const tuple<_TElements...>& __t, |
1455 | const tuple<_UElements...>& __u) |
1456 | { return __u < __t; } |
1457 | |
1458 | template<typename... _TElements, typename... _UElements> |
1459 | constexpr bool |
1460 | operator<=(const tuple<_TElements...>& __t, |
1461 | const tuple<_UElements...>& __u) |
1462 | { return !(__u < __t); } |
1463 | |
1464 | template<typename... _TElements, typename... _UElements> |
1465 | constexpr bool |
1466 | operator>=(const tuple<_TElements...>& __t, |
1467 | const tuple<_UElements...>& __u) |
1468 | { return !(__t < __u); } |
1469 | #endif // three_way_comparison |
1470 | |
1471 | // NB: DR 705. |
1472 | template<typename... _Elements> |
1473 | constexpr tuple<typename __decay_and_strip<_Elements>::__type...> |
1474 | make_tuple(_Elements&&... __args) |
1475 | { |
1476 | typedef tuple<typename __decay_and_strip<_Elements>::__type...> |
1477 | __result_type; |
1478 | return __result_type(std::forward<_Elements>(__args)...); |
1479 | } |
1480 | |
1481 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1482 | // 2275. Why is forward_as_tuple not constexpr? |
1483 | /// std::forward_as_tuple |
1484 | template<typename... _Elements> |
1485 | constexpr tuple<_Elements&&...> |
1486 | forward_as_tuple(_Elements&&... __args) noexcept |
1487 | { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } |
1488 | |
1489 | template<size_t, typename, typename, size_t> |
1490 | struct __make_tuple_impl; |
1491 | |
1492 | template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm> |
1493 | struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> |
1494 | : __make_tuple_impl<_Idx + 1, |
1495 | tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>, |
1496 | _Tuple, _Nm> |
1497 | { }; |
1498 | |
1499 | template<std::size_t _Nm, typename _Tuple, typename... _Tp> |
1500 | struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> |
1501 | { |
1502 | typedef tuple<_Tp...> __type; |
1503 | }; |
1504 | |
1505 | template<typename _Tuple> |
1506 | struct __do_make_tuple |
1507 | : __make_tuple_impl<0, tuple<>, _Tuple, std::tuple_size<_Tuple>::value> |
1508 | { }; |
1509 | |
1510 | // Returns the std::tuple equivalent of a tuple-like type. |
1511 | template<typename _Tuple> |
1512 | struct __make_tuple |
1513 | : public __do_make_tuple<__remove_cvref_t<_Tuple>> |
1514 | { }; |
1515 | |
1516 | // Combines several std::tuple's into a single one. |
1517 | template<typename...> |
1518 | struct __combine_tuples; |
1519 | |
1520 | template<> |
1521 | struct __combine_tuples<> |
1522 | { |
1523 | typedef tuple<> __type; |
1524 | }; |
1525 | |
1526 | template<typename... _Ts> |
1527 | struct __combine_tuples<tuple<_Ts...>> |
1528 | { |
1529 | typedef tuple<_Ts...> __type; |
1530 | }; |
1531 | |
1532 | template<typename... _T1s, typename... _T2s, typename... _Rem> |
1533 | struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...> |
1534 | { |
1535 | typedef typename __combine_tuples<tuple<_T1s..., _T2s...>, |
1536 | _Rem...>::__type __type; |
1537 | }; |
1538 | |
1539 | // Computes the result type of tuple_cat given a set of tuple-like types. |
1540 | template<typename... _Tpls> |
1541 | struct __tuple_cat_result |
1542 | { |
1543 | typedef typename __combine_tuples |
1544 | <typename __make_tuple<_Tpls>::__type...>::__type __type; |
1545 | }; |
1546 | |
1547 | // Helper to determine the index set for the first tuple-like |
1548 | // type of a given set. |
1549 | template<typename...> |
1550 | struct __make_1st_indices; |
1551 | |
1552 | template<> |
1553 | struct __make_1st_indices<> |
1554 | { |
1555 | typedef std::_Index_tuple<> __type; |
1556 | }; |
1557 | |
1558 | template<typename _Tp, typename... _Tpls> |
1559 | struct __make_1st_indices<_Tp, _Tpls...> |
1560 | { |
1561 | typedef typename std::_Build_index_tuple<std::tuple_size< |
1562 | typename std::remove_reference<_Tp>::type>::value>::__type __type; |
1563 | }; |
1564 | |
1565 | // Performs the actual concatenation by step-wise expanding tuple-like |
1566 | // objects into the elements, which are finally forwarded into the |
1567 | // result tuple. |
1568 | template<typename _Ret, typename _Indices, typename... _Tpls> |
1569 | struct __tuple_concater; |
1570 | |
1571 | template<typename _Ret, std::size_t... _Is, typename _Tp, typename... _Tpls> |
1572 | struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> |
1573 | { |
1574 | template<typename... _Us> |
1575 | static constexpr _Ret |
1576 | _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) |
1577 | { |
1578 | typedef typename __make_1st_indices<_Tpls...>::__type __idx; |
1579 | typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; |
1580 | return __next::_S_do(std::forward<_Tpls>(__tps)..., |
1581 | std::forward<_Us>(__us)..., |
1582 | std::get<_Is>(std::forward<_Tp>(__tp))...); |
1583 | } |
1584 | }; |
1585 | |
1586 | template<typename _Ret> |
1587 | struct __tuple_concater<_Ret, std::_Index_tuple<>> |
1588 | { |
1589 | template<typename... _Us> |
1590 | static constexpr _Ret |
1591 | _S_do(_Us&&... __us) |
1592 | { |
1593 | return _Ret(std::forward<_Us>(__us)...); |
1594 | } |
1595 | }; |
1596 | |
1597 | /// tuple_cat |
1598 | template<typename... _Tpls, typename = typename |
1599 | enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type> |
1600 | constexpr auto |
1601 | tuple_cat(_Tpls&&... __tpls) |
1602 | -> typename __tuple_cat_result<_Tpls...>::__type |
1603 | { |
1604 | typedef typename __tuple_cat_result<_Tpls...>::__type __ret; |
1605 | typedef typename __make_1st_indices<_Tpls...>::__type __idx; |
1606 | typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; |
1607 | return __concater::_S_do(std::forward<_Tpls>(__tpls)...); |
1608 | } |
1609 | |
1610 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1611 | // 2301. Why is tie not constexpr? |
1612 | /// tie |
1613 | template<typename... _Elements> |
1614 | constexpr tuple<_Elements&...> |
1615 | tie(_Elements&... __args) noexcept |
1616 | { return tuple<_Elements&...>(__args...); } |
1617 | |
1618 | /// swap |
1619 | template<typename... _Elements> |
1620 | _GLIBCXX20_CONSTEXPR |
1621 | inline |
1622 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
1623 | // Constrained free swap overload, see p0185r1 |
1624 | typename enable_if<__and_<__is_swappable<_Elements>...>::value |
1625 | >::type |
1626 | #else |
1627 | void |
1628 | #endif |
1629 | swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) |
1630 | noexcept(noexcept(__x.swap(__y))) |
1631 | { __x.swap(__y); } |
1632 | |
1633 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
1634 | template<typename... _Elements> |
1635 | _GLIBCXX20_CONSTEXPR |
1636 | typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type |
1637 | swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete; |
1638 | #endif |
1639 | |
1640 | // A class (and instance) which can be used in 'tie' when an element |
1641 | // of a tuple is not required. |
1642 | // _GLIBCXX14_CONSTEXPR |
1643 | // 2933. PR for LWG 2773 could be clearer |
1644 | struct _Swallow_assign |
1645 | { |
1646 | template<class _Tp> |
1647 | _GLIBCXX14_CONSTEXPRconstexpr const _Swallow_assign& |
1648 | operator=(const _Tp&) const |
1649 | { return *this; } |
1650 | }; |
1651 | |
1652 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1653 | // 2773. Making std::ignore constexpr |
1654 | _GLIBCXX17_INLINEinline constexpr _Swallow_assign ignore{}; |
1655 | |
1656 | /// Partial specialization for tuples |
1657 | template<typename... _Types, typename _Alloc> |
1658 | struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { }; |
1659 | |
1660 | // See stl_pair.h... |
1661 | /** "piecewise construction" using a tuple of arguments for each member. |
1662 | * |
1663 | * @param __first Arguments for the first member of the pair. |
1664 | * @param __second Arguments for the second member of the pair. |
1665 | * |
1666 | * The elements of each tuple will be used as the constructor arguments |
1667 | * for the data members of the pair. |
1668 | */ |
1669 | template<class _T1, class _T2> |
1670 | template<typename... _Args1, typename... _Args2> |
1671 | _GLIBCXX20_CONSTEXPR |
1672 | inline |
1673 | pair<_T1, _T2>:: |
1674 | pair(piecewise_construct_t, |
1675 | tuple<_Args1...> __first, tuple<_Args2...> __second) |
1676 | : pair(__first, __second, |
1677 | typename _Build_index_tuple<sizeof...(_Args1)>::__type(), |
1678 | typename _Build_index_tuple<sizeof...(_Args2)>::__type()) |
1679 | { } |
1680 | |
1681 | template<class _T1, class _T2> |
1682 | template<typename... _Args1, std::size_t... _Indexes1, |
1683 | typename... _Args2, std::size_t... _Indexes2> |
1684 | _GLIBCXX20_CONSTEXPR inline |
1685 | pair<_T1, _T2>:: |
1686 | pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2, |
1687 | _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>) |
1688 | : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...), |
1689 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) |
1690 | { } |
1691 | |
1692 | #if __cplusplus201703L >= 201703L |
1693 | |
1694 | // Unpack a std::tuple into a type trait and use its value. |
1695 | // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value. |
1696 | // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value. |
1697 | // Otherwise the result is false (because we don't know if std::get throws). |
1698 | template<template<typename...> class _Trait, typename _Tp, typename _Tuple> |
1699 | inline constexpr bool __unpack_std_tuple = false; |
1700 | |
1701 | template<template<typename...> class _Trait, typename _Tp, typename... _Up> |
1702 | inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>> |
1703 | = _Trait<_Tp, _Up...>::value; |
1704 | |
1705 | template<template<typename...> class _Trait, typename _Tp, typename... _Up> |
1706 | inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&> |
1707 | = _Trait<_Tp, _Up&...>::value; |
1708 | |
1709 | template<template<typename...> class _Trait, typename _Tp, typename... _Up> |
1710 | inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>> |
1711 | = _Trait<_Tp, const _Up...>::value; |
1712 | |
1713 | template<template<typename...> class _Trait, typename _Tp, typename... _Up> |
1714 | inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&> |
1715 | = _Trait<_Tp, const _Up&...>::value; |
1716 | |
1717 | # define __cpp_lib_apply201603 201603 |
1718 | |
1719 | template <typename _Fn, typename _Tuple, size_t... _Idx> |
1720 | constexpr decltype(auto) |
1721 | __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) |
1722 | { |
1723 | return std::__invoke(std::forward<_Fn>(__f), |
1724 | std::get<_Idx>(std::forward<_Tuple>(__t))...); |
1725 | } |
1726 | |
1727 | template <typename _Fn, typename _Tuple> |
1728 | constexpr decltype(auto) |
1729 | apply(_Fn&& __f, _Tuple&& __t) |
1730 | noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>) |
1731 | { |
1732 | using _Indices |
1733 | = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>; |
1734 | return std::__apply_impl(std::forward<_Fn>(__f), |
1735 | std::forward<_Tuple>(__t), |
1736 | _Indices{}); |
1737 | } |
1738 | |
1739 | #define __cpp_lib_make_from_tuple201606 201606 |
1740 | |
1741 | template <typename _Tp, typename _Tuple, size_t... _Idx> |
1742 | constexpr _Tp |
1743 | __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) |
1744 | { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } |
1745 | |
1746 | template <typename _Tp, typename _Tuple> |
1747 | constexpr _Tp |
1748 | make_from_tuple(_Tuple&& __t) |
1749 | noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>) |
1750 | { |
1751 | return __make_from_tuple_impl<_Tp>( |
1752 | std::forward<_Tuple>(__t), |
1753 | make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>{}); |
1754 | } |
1755 | #endif // C++17 |
1756 | |
1757 | /// @} |
1758 | |
1759 | _GLIBCXX_END_NAMESPACE_VERSION |
1760 | } // namespace std |
1761 | |
1762 | #endif // C++11 |
1763 | |
1764 | #endif // _GLIBCXX_TUPLE |