AData.h revision 85042380bf7ee3a43eb4cccacdaadfbbafc1522f
1e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/* 2e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Copyright (C) 2016 The Android Open Source Project 3e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 4e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License"); 5e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * you may not use this file except in compliance with the License. 6e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * You may obtain a copy of the License at 7e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 8e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * http://www.apache.org/licenses/LICENSE-2.0 9e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 10e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Unless required by applicable law or agreed to in writing, software 11e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS, 12e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * See the License for the specific language governing permissions and 14e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * limitations under the License. 15e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 16e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 17e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#ifndef STAGEFRIGHT_FOUNDATION_A_DATA_H_ 18e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#define STAGEFRIGHT_FOUNDATION_A_DATA_H_ 19e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 20e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <memory> // for std::shared_ptr, weak_ptr and unique_ptr 21e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <type_traits> // for std::aligned_union 22e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 23e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <utils/StrongPointer.h> // for android::sp and wp 24e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 25e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <media/stagefright/foundation/TypeTraits.h> 26e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <media/stagefright/foundation/Flagged.h> 27e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 2885042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnar#undef HIDE 2985042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnar#define HIDE __attribute__((visibility("hidden"))) 3085042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnar 31e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarnamespace android { 32e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 33e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 34e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData is a flexible union type that supports non-POD members. It supports arbitrary types as long 35e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * as they are either moveable or copyable. 36e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 37e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Internally, AData is using AUnion - a structure providing the union support. AUnion should not 38e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * be used by generic code as it is very unsafe - it opens type aliasing errors where an object of 39e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * one type can be easily accessed as an object of another type. AData prevents this. 40e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 41e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData allows a custom type flagger to be used for future extensions (e.g. allowing automatic 42e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * type conversion). A strict and a relaxed flagger are provided as internal types. 43e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 44e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Use as follows: 45e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 46e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<int, float>::Basic data; // strict type support 47e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * int i = 1; 48e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * float f = 7.0f; 49e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 50e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * data.set(5); 51e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(data.find(&i)); 52e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(data.find(&f)); 53e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_EQ(i, 5); 54e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 55e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * data.set(6.0f); 56e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(data.find(&i)); 57e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(data.find(&f)); 58e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_EQ(f, 6.0f); 59e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 60e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<int, sp<RefBase>>::RelaxedBasic objdata; // relaxed type support 61e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * sp<ABuffer> buf = new ABuffer(16), buf2; 62e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * sp<RefBase> obj; 63e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 64e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * objdata.set(buf); 65e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(objdata.find(&buf2)); 66e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_EQ(buf, buf2); 67e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(objdata.find(&i)); 68e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(objdata.find(&obj)); 69e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(obj == buf); 70e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 71e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * obj = buf; 72e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * objdata.set(obj); // storing as sp<RefBase> 73e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(objdata.find(&buf2)); // not stored as ABuffer(!) 74e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(objdata.find(&obj)); 75e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 76e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 77e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \cond Internal 78e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 79e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 80e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper class to call constructor and destructor for a specific type in AUnion. 81e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This class is needed as member function specialization is not allowed for a 82e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * templated class. 83e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 8485042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AUnion_impl { 85e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 86e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Calls placement constuctor for type T with arbitrary arguments for a storage at an address. 87e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Storage MUST be large enough to contain T. 88e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Also clears the slack space after type T. \todo This is not technically needed, so we may 89e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * choose to do this just for debugging. 90e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 91e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param totalSize size of the storage 92e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param addr pointer to where object T should be constructed 93e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param args arbitrary arguments for constructor 94e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 95e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T, typename ...Args> 96e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void emplace(size_t totalSize, T *addr, Args&&... args) { 97e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar new(addr)T(std::forward<Args>(args)...); 98e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // clear slack space - this is not technically required 99e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar constexpr size_t size = sizeof(T); 100e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar memset(reinterpret_cast<uint8_t*>(addr) + size, 0, totalSize - size); 101e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 102e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 103e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 104e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Calls destuctor for an object of type T located at a specific address. 105e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 106e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \note we do not clear the storage in this case as the storage should not be used 107e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * until another object is placed there, at which case the storage will be cleared. 108e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 109e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param addr pointer to where object T is stored 110e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 111e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 112e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void del(T *addr) { 113e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar addr->~T(); 114e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 115e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 116e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 117e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** Constructor specialization for void type */ 118e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<> 11985042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos MolnarHIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) { 120e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar memset(addr, 0, totalSize); 121e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar} 122e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 123e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** Destructor specialization for void type */ 124e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<> 12585042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos MolnarHIDE inline void _AUnion_impl::del<void>(void *) { 126e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar} 127e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 128e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \endcond 129e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 130e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 131e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * A templated union class that can contain specific types of data, and provides 132e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * constructors, destructor and access methods strictly for those types. 133e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 134e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \note This class is VERY UNSAFE compared to a union, but it allows non-POD unions. 135e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * In particular care must be taken that methods are called in a careful order to 136e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * prevent accessing objects of one type as another type. This class provides no 137e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * facilities to help with this ordering. This is meant to be wrapped by safer 138e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * utility classes that do that. 139e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 140e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Ts types stored in this union. 141e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 142e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename ...Ts> 143e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct AUnion { 144e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarprivate: 145e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using _type = typename std::aligned_union<0, Ts...>::type; ///< storage type 146e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _type mValue; ///< storage 147e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 148e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarpublic: 149e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 150e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constructs an object of type T with arbitrary arguments in this union. After this call, 151e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * this union will contain this object. 152e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 153e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This method MUST be called only when either 1) no object or 2) a void object (equivalent to 154e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * no object) is contained in this union. 155e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 156e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to be constructed. This must be one of the template parameters of 157e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * the union class with the same cv-qualification, or void. 158e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param args arbitrary arguments for the constructor 159e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 160e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template< 161e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, typename ...Args, 162e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type> 163e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline void emplace(Args&&... args) { 164e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _AUnion_impl::emplace( 165e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar sizeof(_type), reinterpret_cast<T*>(&mValue), std::forward<Args>(args)...); 166e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 167e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 168e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 169e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Destructs an object of type T in this union. After this call, this union will contain no 170e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * object. 171e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 172e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This method MUST be called only when this union contains an object of type T. 173e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 174e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to be destructed. This must be one of the template parameters of 175e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * the union class with the same cv-qualification, or void. 176e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 177e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template< 178e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 179e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type> 180e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline void del() { 181e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _AUnion_impl::del(reinterpret_cast<T*>(&mValue)); 182e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 183e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 184e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 185e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Returns a const reference to the object of type T in this union. 186e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 187e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This method MUST be called only when this union contains an object of type T. 188e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 189e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to be returned. This must be one of the template parameters of 190e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * the union class with the same cv-qualification. 191e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 192e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template< 193e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 194e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type> 195e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline const T &get() const { 196e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return *reinterpret_cast<const T*>(&mValue); 197e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 198e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 199e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 200e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Returns a reference to the object of type T in this union. 201e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 202e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This method MUST be called only when this union contains an object of type T. 203e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 204e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to be returned. This must be one of the template parameters of 205e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * the union class with the same cv-qualification. 206e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 207e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 208e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline T &get() { 209e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return *reinterpret_cast<T*>(&mValue); 210e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 211e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 212e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 213e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 214e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper utility class that copies an object of type T to a destination. 215e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 216e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * T must be copy assignable or copy constructible. 217e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 218e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * It provides: 219e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 220e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * void assign(T*, const U&) // for copiable types - this leaves the source unchanged, hence const. 221e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 222e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to assign to 223e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 224e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate< 225e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 226e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar bool=std::is_copy_assignable<T>::value> 22785042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_copier { 228e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_copy_assignable<T>::value, "T must be copy assignable here"); 229e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 230e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 231e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Copies src to data without modifying data. 232e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 233e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param data pointer to destination 234e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param src source object 235e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 236e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(T *data, const T &src) { 237e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = src; 238e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 239e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 240e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename U> 241e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type; 242e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 243e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 244e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<> 245e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 246e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>> 247e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(sp<Tp> *data, const sp<U> &src) { 248e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = static_cast<Tp*>(src.get()); 249e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 250e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 251e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<wp<Tp>>> 252e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(wp<Tp> *data, const wp<U> &src) { 253e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar sp<U> __tmp = src.promote(); 254e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = static_cast<Tp*>(__tmp.get()); 255e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 256e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 257e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>> 258e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(sp<Tp> *data, sp<U> &&src) { 259e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar sp<U> __tmp = std::move(src); // move src out as get cannot 260e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = static_cast<Tp*>(__tmp.get()); 261e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 262e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 263e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>> 264e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::shared_ptr<Tp> *data, const std::shared_ptr<U> &src) { 265e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = std::static_pointer_cast<Tp>(src); 266e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 267e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 268e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>> 269e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) { 270e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot 271e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = std::static_pointer_cast<Tp>(__tmp); 272e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 273e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 274e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::weak_ptr<Tp>>> 275e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::weak_ptr<Tp> *data, const std::weak_ptr<U> &src) { 276e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = std::static_pointer_cast<Tp>(src.lock()); 277e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 278e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 279e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the 280e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that 281e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // they are stored as shared_ptrs. 282e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 283e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method 284e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * is not enough to detect this, only if someone is trying to find the shared_ptr. 285e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 286e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U> 287e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::shared_ptr<Tp> *, const std::weak_ptr<U> &) { 288e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_same<Tp, void>::value, 289e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs"); 290e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 291e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 292e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 293e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 294e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization for non copy assignable, but copy constructible types. 295e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 296e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \todo Test this. No basic classes are copy constructible but not assignable. 297e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 298e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 299e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T> 30085042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_copier<T, false> { 301e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(!std::is_copy_assignable<T>::value, "T must not be copy assignable here"); 302e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible here"); 303e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 304e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void copy(T *data, const T &src) { 305e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar data->~T(); 306e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar new(data)T(src); 307e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 308e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 309e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 310e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 311e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper utility class that moves an object of type T to a destination. 312e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 313e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * T must be move assignable or move constructible. 314e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 315e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * It provides multiple methods: 316e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 317e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * void assign(T*, T&&) 318e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 319e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to assign 320e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 321e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate< 322e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 323e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar bool=std::is_move_assignable<T>::value> 32485042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_mover { 325e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_move_assignable<T>::value, "T must be move assignable here"); 326e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 327e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 328e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Moves src to data while likely modifying it. 329e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 330e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param data pointer to destination 331e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param src source object 332e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 333e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(T *data, T &&src) { 334e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = std::move(src); 335e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 336e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 337e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename U> 338e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type; 339e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 340e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 341e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<> 342e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 343e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>> 344e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(sp<Tp> *data, sp<U> &&src) { 345e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar sp<U> __tmp = std::move(src); // move src out as get cannot 346e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = static_cast<Tp*>(__tmp.get()); 347e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 348e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 349e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>> 350e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) { 351e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot 352e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = std::static_pointer_cast<Tp>(__tmp); 353e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 354e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 355e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename Td, typename U, typename Ud, 356e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=enable_if_T_is_same_as<std::unique_ptr<Tp, Td>>> 357e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::unique_ptr<Tp, Td> *data, std::unique_ptr<U, Ud> &&src) { 358e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *data = std::unique_ptr<Tp, Td>(static_cast<Tp*>(src.release())); 359e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 360e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 361e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the 362e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that 363e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // they are stored as shared_ptrs. 364e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 365e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method 366e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * is not enough to detect this, only if someone is trying to remove the shared_ptr. 367e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 368e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U> 369e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::shared_ptr<Tp> *, std::weak_ptr<U> &&) { 370e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_same<Tp, void>::value, 371e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs"); 372e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 373e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 374e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // unique_ptrs are implicitly convertible to shared_ptrs but not vice versa, but picking the 375e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // first compatible type in Ts requires having unique_ptrs types before shared_ptrs types, so 376e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // that they are stored as unique_ptrs. 377e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 378e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Provide sensible error message if encountering shared_ptr/unique_ptr ambiguity. This method 379e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * is not enough to detect this, only if someone is trying to remove the unique_ptr. 380e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 381e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Tp, typename U> 382e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(std::unique_ptr<Tp> *, std::shared_ptr<U> &&) { 383e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_same<Tp, void>::value, 384e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar "unique/shared pointer ambiguity. move unique ptr types before shared_ptrs"); 385e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 386e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 387e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 388e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 389e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization for non move assignable, but move constructible types. 390e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 391e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \todo Test this. No basic classes are move constructible but not assignable. 392e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 393e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 394e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T> 39585042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_mover<T, false> { 396e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(!std::is_move_assignable<T>::value, "T must not be move assignable here"); 397e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_move_constructible<T>::value, "T must be move constructible here"); 398e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 399e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static void assign(T *data, T &&src) { 400e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar data->~T(); 401e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar new(data)T(std::move(src)); 402e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 403e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 404e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 405e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 406e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper template that deletes an object of a specific type (member) in an AUnion. 407e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 408e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Flagger type flagger class (see AData) 409e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param U AUnion object in which the member should be deleted 410e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Ts types to consider for the member 411e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 412e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename Flagger, typename U, typename ...Ts> 41385042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_deleter; 414e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 415e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 416e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there are still types to consider (T and rest) 417e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 418e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename Flagger, typename U, typename T, typename ...Ts> 41985042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_deleter<Flagger, U, T, Ts...> { 420e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static bool del(typename Flagger::type flags, U &data) { 421e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) { 422e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar data.template del<T>(); 423e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 424e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 425e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return _AData_deleter<Flagger, U, Ts...>::del(flags, data); 426e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 427e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 428e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 429e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 430e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there are no more types to consider. 431e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 432e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename Flagger, typename U> 43385042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_deleter<Flagger, U> { 434e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline static bool del(typename Flagger::type, U &) { 435e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return false; 436e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 437e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 438e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 439e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** 440e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Container that can store an arbitrary object of a set of specified types. 441e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 442e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This struct is an outer class that contains various inner classes based on desired type 443e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * strictness. The following inner classes are supported: 444e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 445e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Basic - strict type support using uint32_t flag. 446e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 447e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Strict<Flag> - strict type support using custom flag. 448e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Relaxed<Flag, MaxSize, Align> 449e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * - relaxed type support with compatible (usually derived) class support 450e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * for pointer types with added size checking for minimal additional 451e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * safety. 452e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 453e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::RelaxedBasic - strict type support using uint32_t flag. 454e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 455e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Custom<flagger> - custom type support (flaggers determine the supported types 456e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * and the base type to use for each) 457e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 458e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 459e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename ...Ts> 460e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct AData { 461e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarprivate: 462e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(are_unique<Ts...>::value, "types must be unique"); 463e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 464e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr size_t num_types = sizeof...(Ts); ///< number of types to support 465e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 466e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarpublic: 467e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 468e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Default (strict) type flagger provided. 469e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 470e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * The default flagger simply returns the index of the type within Ts, or 0 for void. 471e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 472e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Type flaggers return a flag for a supported type. 473e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 474e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * They must provide: 475e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 476e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * - a flagFor(T*) method for supported types _and_ for T=void. T=void is used to mark that no 477e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * object is stored in the container. For this, an arbitrary unique value may be returned. 478e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * - a mask field that contains the flag mask. 479e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * - a canDeleteAs(Flag, Flag) flag comparison method that checks if a type of a flag can be 480e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * deleted as another type. 481e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 482e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Flag the underlying unsigned integral to use for the flags. 483e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 484e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Flag> 485e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar struct flagger { 486e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar private: 487e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned"); 488e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_integral<Flag>::value, "Flag must be an integral type"); 489e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 490e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag count = num_types + 1; 491e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 492e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar public: 493e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typedef Flag type; ///< flag type 494e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 495e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag mask = _Flagged_helper::minMask<Flag>(count); ///< flag mask 496e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 497e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 498e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Return the stored type for T. This is itself. 499e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 500e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 501e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar struct store { 502e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typedef T as_type; ///< the base type that T is stored as 503e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar }; 504e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 505e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 506e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constexpr method that returns if two flags are compatible for deletion. 507e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 508e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param objectFlag flag for object to be deleted 509e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param deleteFlag flag for type that object is to be deleted as 510e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 511e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) { 512e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // default flagger requires strict type equality 513e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return objectFlag == deleteFlag; 514e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 515e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 516e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 517e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constexpr method that returns the flag to use for a given type. 518e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 519e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Function overload for void*. 520e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 521e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(void*) { 522e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return 0u; 523e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 524e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 525e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 526e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constexpr method that returns the flag to use for a given supported type (T). 527e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 528e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type> 529e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(T*) { 530e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return find_first<T, Ts...>::index; 531e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 532e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar }; 533e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 534e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 535e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Relaxed flagger returns the index of the type within Ts. However, for pointers T* it returns 536e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * the first type in Ts that T* can be converted into (this is normally a base type, but also 537e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * works for sp<>, shared_ptr<> or unique_ptr<>). For a bit more strictness, the flag also 538e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * contains the size of the class to avoid finding objects that were stored as a different 539e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * derived class of the same base class. 540e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 541e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Flag is basically the index of the (base) type in Ts multiplied by the max size stored plus 542e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * the size of the type (divided by alignment) for derived pointer types. 543e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 544e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param MaxSize max supported size for derived class pointers 545e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Align alignment to assume for derived class pointers 546e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 547e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Flag, size_t MaxSize=1024, size_t Align=4> 548e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar struct relaxed_flagger { 549e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar private: 550e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned"); 551e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::is_integral<Flag>::value, "Flag must be an integral type"); 552e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 553e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag count = num_types + 1; 554e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static_assert(std::numeric_limits<Flag>::max() / count > (MaxSize / Align), 555e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar "not enough bits to fit into flag"); 556e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 557e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag max_size_stored = MaxSize / Align + 1; 558e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 559e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // T can be converted if it's size is <= MaxSize and it can be converted to one of the Ts 560e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T, size_t size> 561e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using enable_if_can_be_converted = typename std::enable_if< 562e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar (size / Align < max_size_stored 563e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar && find_first_convertible_to<T, Ts...>::index)>::type; 564e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 565e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 566e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename W, typename T, typename=enable_if_can_be_converted<W, sizeof(T)>> 567e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag relaxedFlagFor(W*, T*) { 568e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return find_first_convertible_to<W, Ts...>::index * max_size_stored 569e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar + (is_one_of<W, Ts...>::value ? 0 : (sizeof(T) / Align)); 570e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 571e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 572e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar public: 573e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typedef Flag type; ///< flag type 574e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 575e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag mask = 576e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _Flagged_helper::minMask<Flag>(count * max_size_stored); ///< flag mask 577e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 578e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 579e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constexpr method that returns if two flags are compatible for deletion. 580e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 581e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param objectFlag flag for object to be deleted 582e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param deleteFlag flag for type that object is to be deleted as 583e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 584e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) { 585e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // can delete if objects have the same base type 586e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return 587e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar objectFlag / max_size_stored == deleteFlag / max_size_stored && 588e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar (deleteFlag % max_size_stored) == 0; 589e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 590e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 591e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 592e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constexpr method that returns the flag to use for a given type. 593e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 594e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Function overload for void*. 595e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 596e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(void*) { 597e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return 0u; 598e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 599e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 600e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 601e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constexpr method that returns the flag to use for a given supported type (T). 602e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 603e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This is a member method to enable both overloading as well as template specialization. 604e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 605e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type> 606e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(T*) { 607e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return find_first<T, Ts...>::index * max_size_stored; 608e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 609e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 610e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 611e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * For precaution, we only consider converting pointers to their base classes. 612e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 613e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 614e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 615e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization for derived class pointers and managed pointers. 616e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 617e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 618e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(T**p) { return relaxedFlagFor(p, (T*)0); } 619e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 620e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(std::shared_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); } 621e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 622e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(std::unique_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); } 623e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 624e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(std::weak_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); } 625e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 626e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(sp<T>*p) { return relaxedFlagFor(p, (T*)0); } 627e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 628e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar static constexpr Flag flagFor(wp<T>*p) { return relaxedFlagFor(p, (T*)0); } 629e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 630e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 631e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Type support template that provodes the stored type for T. 632e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This is itself if it is one of Ts, or the first type in Ts that T is convertible to. 633e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 634e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * NOTE: This template may provide a base class for an unsupported type. Support is 635e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * determined by flagFor(). 636e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 637e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 638e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar struct store { 639e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typedef typename std::conditional< 640e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar is_one_of<T, Ts...>::value, 641e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar T, 642e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename find_first_convertible_to<T, Ts...>::type>::type as_type; 643e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar }; 644e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar }; 645e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 646e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 647e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Implementation of AData. 648e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 649e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Flagger> 650e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar struct Custom : protected Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask> { 651e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using data_t = AUnion<Ts...>; 652e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using base_t = Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask>; 653e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 654e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 655e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Constructor. Initializes this to a container that does not contain any object. 656e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 657e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar Custom() : base_t(Flagger::flagFor((void*)0)) { } 658e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 659e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 660e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Removes the contained object, if any. 661e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 662e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar ~Custom() { 663e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (!this->clear()) { 664e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar __builtin_trap(); 665e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // std::cerr << "could not delete data of type " << this->flags() << std::endl; 666e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 667e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 668e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 669e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 670e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Returns whether there is any object contained. 671e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 672e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar inline bool used() const { 673e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return this->flags() != Flagger::flagFor((void*)0); 674e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 675e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 676e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 677e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Removes the contained object, if any. Returns true if there are no objects contained, 678e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * or false on any error (this is highly unexpected). 679e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 680e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar bool clear() { 681e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (this->used()) { 682e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (_AData_deleter<Flagger, data_t, Ts...>::del(this->flags(), this->get())) { 683e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar this->setFlags(Flagger::flagFor((void*)0)); 684e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 685e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 686e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return false; 687e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 688e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 689e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 690e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 691e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename T> 692e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using is_supported_by_flagger = 693e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename std::enable_if<Flagger::flagFor((T*)0) != Flagger::flagFor((void*)0)>::type; 694e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 695e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 696e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Checks if there is a copiable object of type T in this container. If there is, it copies 697e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * that object into the provided address and returns true. Otherwise, it does nothing and 698e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * returns false. 699e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 700e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This method normally requires a flag equality between the stored and retrieved types. 701e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * However, it also allows retrieving the stored object as the stored type 702e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * (usually base type). 703e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 704e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to sought 705e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param data address at which the object should be retrieved 706e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 707e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \return true if the object was retrieved. false if it was not. 708e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 709e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template< 710e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 711e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=is_supported_by_flagger<T>> 712e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar bool find(T *data) const { 713e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using B = typename Flagger::template store<T>::as_type; 714e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (this->flags() == Flagger::flagFor((T*)0) || 715e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) { 716e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _AData_copier<T>::assign(data, this->get().template get<B>()); 717e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 718e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 719e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return false; 720e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 721e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 722e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 723e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Checks if there is an object of type T in this container. If there is, it moves that 724e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * object into the provided address and returns true. Otherwise, it does nothing and returns 725e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * false. 726e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 727e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This method normally requires a flag equality between the stored and retrieved types. 728e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * However, it also allows retrieving the stored object as the stored type 729e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * (usually base type). 730e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 731e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to sought 732e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param data address at which the object should be retrieved. 733e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 734e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \return true if the object was retrieved. false if it was not. 735e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 736e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template< 737e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 738e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=is_supported_by_flagger<T>> 739e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar bool remove(T *data) { 740e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using B = typename Flagger::template store<T>::as_type; 741e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (this->flags() == Flagger::flagFor((T*)0) || 742e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) { 743e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _AData_mover<T>::assign(data, std::move(this->get().template get<B>())); 744e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 745e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 746e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return false; 747e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 748e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 749e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 750e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Stores an object into this container by copying. If it was successful, returns true. 751e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Otherwise, (e.g. it could not destroy the already stored object) it returns false. This 752e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * latter would be highly unexpected. 753e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 754e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to store 755e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param data object to store 756e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 757e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \return true if the object was stored. false if it was not. 758e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 759e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template< 760e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 761e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=is_supported_by_flagger<T>, 762e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=typename std::enable_if< 763e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar std::is_copy_constructible<T>::value || 764e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar (std::is_default_constructible<T>::value && 765e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar std::is_copy_assignable<T>::value)>::type> 766e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar bool set(const T &data) { 767e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using B = typename Flagger::template store<T>::as_type; 768e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 769e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // if already contains an object of this type, simply assign 770e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) { 771e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _AData_copier<B>::assign(&this->get().template get<B>(), data); 772e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 773e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } else if (this->used()) { 774e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // destroy previous object 775e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (!this->clear()) { 776e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return false; 777e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 778e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 779e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar this->get().template emplace<B>(data); 780e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar this->setFlags(Flagger::flagFor((T *)0)); 781e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 782e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 783e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 784e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 785e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Moves an object into this container. If it was successful, returns true. Otherwise, 786e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * (e.g. it could not destroy the already stored object) it returns false. This latter 787e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * would be highly unexpected. 788e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 789e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to store 790e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param data object to store 791e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 792e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \return true if the object was stored. false if it was not. 793e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 794e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template< 795e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename T, 796e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar typename=is_supported_by_flagger<T>> 797e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar bool set(T &&data) { 798e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using B = typename Flagger::template store<T>::as_type; 799e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 800e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // if already contains an object of this type, simply assign 801e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) { 802e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar _AData_mover<B>::assign(&this->get().template get<B>(), std::forward<T&&>(data)); 803e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 804e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } else if (this->used()) { 805e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar // destroy previous object 806e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar if (!this->clear()) { 807e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return false; 808e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 809e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 810e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar this->get().template emplace<B>(std::forward<T&&>(data)); 811e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar this->setFlags(Flagger::flagFor((T *)0)); 812e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar return true; 813e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar } 814e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar }; 815e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 816e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 817e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Basic AData using the default type flagger and requested flag type. 818e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 819e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Flag desired flag type to use. Must be an unsigned and std::integral type. 820e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 821e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Flag> 822e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using Strict = Custom<flagger<Flag>>; 823e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 824e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 825e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Basic AData using the default type flagger and uint32_t flag. 826e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 827e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using Basic = Strict<uint32_t>; 828e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 829e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 830e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData using the relaxed type flagger for max size and requested flag type. 831e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * 832e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Flag desired flag type to use. Must be an unsigned and std::integral type. 833e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 834e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar template<typename Flag, size_t MaxSize = 1024, size_t Align = 4> 835e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using Relaxed = Custom<relaxed_flagger<Flag, MaxSize, Align>>; 836e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 837e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar /** 838e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Basic AData using the relaxed type flagger and uint32_t flag. 839e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */ 840e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar using RelaxedBasic = Relaxed<uint32_t>; 841e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}; 842e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 843e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar} // namespace android 844e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 845e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#endif // STAGEFRIGHT_FOUNDATION_A_DATA_H_ 846e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar 847