Changeset 155:784bc286a24d in finroc_plugins_data_ports
- Timestamp:
- 28.03.2020 13:46:45 (3 years ago)
- Branch:
- 17.03
- Children:
- 156:9e42f886e71e, 158:9dfbc0672376
- Phase:
- public
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
api/tBoundedPort.h
r123 r155 44 44 // Internal includes with "" 45 45 //---------------------------------------------------------------------- 46 #include "plugins/data_ports/ tPortCreationInfo.h"46 #include "plugins/data_ports/common/tAbstractDataPortCreationInfo.h" 47 47 #include "plugins/data_ports/optimized/tCheapCopyPort.h" 48 48 #include "plugins/data_ports/api/tSingleThreadedCheapCopyPort.h" 49 #include "plugins/data_ports/api/tPortImplementationTypeTrait.h" 49 50 50 51 //---------------------------------------------------------------------- … … 71 72 * Port with upper and lower bounds for values. 72 73 */ 73 template <typename T , tPortImplementationType TYPE>74 template <typename T> 74 75 class tBoundedPort : public std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<T>, optimized::tCheapCopyPort>::type 75 76 { 76 typedef tPortImplementation<T, TYPE> tImplementationVariation;77 typedef tPortImplementation<T, tPortImplementationTypeTrait<T>::type> tImplementationVariation; 77 78 typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<T>, optimized::tCheapCopyPort>::type tPortBase; 78 79 … … 82 83 public: 83 84 84 tBoundedPort(co nst tPortCreationInfo<T>&creation_info) :85 tBoundedPort(common::tAbstractDataPortCreationInfo creation_info) : 85 86 tPortBase(AdjustCreationInfo(creation_info)), 86 bounds(creation_info.GetBounds()) 87 { 87 bounds(static_cast<const tBounds<T>&>(*creation_info.GetBoundsGeneric())) 88 { 89 } 90 91 /*! 92 * \param creation_info Port creation info 93 * \return Created port 94 */ 95 static common::tAbstractDataPort* CreateInstance(const common::tAbstractDataPortCreationInfo& creation_info) 96 { 97 return new tBoundedPort(creation_info); 88 98 } 89 99 … … 115 125 if (!bounds.InBounds(value)) 116 126 { 117 typename tPortBase::tUnusedManagerPointer new_buffer(optimized::tGlobalBufferPools::Instance().GetUnusedBuffer(this->GetCheaplyCopiedTypeBufferPoolIndex() ).release());127 typename tPortBase::tUnusedManagerPointer new_buffer(optimized::tGlobalBufferPools::Instance().GetUnusedBuffer(this->GetCheaplyCopiedTypeBufferPoolIndex(), this->GetDataType()).release()); 118 128 tImplementationVariation::Assign(new_buffer->GetObject().template GetData<T>(), bounds.GetOutOfBoundsDefault()); 119 129 this->BrowserPublishRaw(new_buffer); // If port is already connected, could this have undesirable side-effects? (I do not think so - otherwise we need to do something more sophisticated here) … … 140 150 * Make sure non-standard assign flag is set 141 151 */ 142 inline static tPortCreationInfo<T> AdjustCreationInfo(tPortCreationInfo<T> creation_info) 143 { 152 static common::tAbstractDataPortCreationInfo& AdjustCreationInfo(common::tAbstractDataPortCreationInfo& creation_info) 153 { 154 if (creation_info.data_type != rrlib::rtti::tDataType<T>() || creation_info.bounds_type != rrlib::rtti::tDataType<T>() || creation_info.bounds.size() < sizeof(tBounds<T>)) 155 { 156 throw std::invalid_argument("Invalid port creation info passed to tBoundedPort"); 157 } 144 158 creation_info.flags |= core::tFrameworkElement::tFlag::NON_STANDARD_ASSIGN; 145 159 return creation_info; -
api/tGenericPortImplementation.cpp
r135 r155 81 81 virtual core::tAbstractPort* CreatePort(const common::tAbstractDataPortCreationInfo& creation_info) override 82 82 { 83 return new tPortBase(creation_info); 83 if (creation_info.create_port_function) 84 { 85 return (*creation_info.create_port_function)(creation_info); 86 } 87 else 88 { 89 return new tPortBase(creation_info); 90 } 84 91 } 85 92 … … 149 156 virtual core::tAbstractPort* CreatePort(const common::tAbstractDataPortCreationInfo& creation_info) override 150 157 { 151 return new tPortBase(creation_info); 158 if (creation_info.create_port_function) 159 { 160 return (*creation_info.create_port_function)(creation_info); 161 } 162 else 163 { 164 return new tPortBase(creation_info); 165 } 152 166 } 153 167 -
api/tPortImplementation.h
r123 r155 51 51 #include "plugins/data_ports/api/tSingleThreadedCheapCopyPort.h" 52 52 #include "plugins/data_ports/standard/tStandardPort.h" 53 #include "plugins/data_ports/tPortCreationInfo.h" 53 54 54 55 //---------------------------------------------------------------------- … … 79 80 * Common implementation for all ports derived from tCheapCopyPort 80 81 */ 81 template <typename T Wrapper, typename TBuffer, tPortImplementationType TYPE, bool BOUNDABLE>82 template <typename T, tPortImplementationType TYPE> 82 83 struct tCheapCopyPortBaseImplementation 83 84 { 84 typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<TBuffer>, optimized::tCheapCopyPort>::type tPortBase; 85 86 static core::tAbstractPort* CreatePort(tPortCreationInfo<TWrapper> creation_info) 87 { 88 creation_info.UnsetDefaultValue(); // TBuffer might differ from TWrapper => corrupts default value (it is set later in tPort) 89 if (creation_info.BoundsSet()) 85 typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<T>, optimized::tCheapCopyPort>::type tPortBase; 86 87 static core::tAbstractPort* CreatePort(const tPortCreationInfo<T>& creation_info) 88 { 89 if (creation_info.create_port_function) 90 90 { 91 #ifdef __nios2__ 92 return new tPortBase(creation_info); 93 #else 94 return new tBoundedPort<TWrapper, TYPE>(creation_info); // Crashes with release mode in gcc 4.6 and nios gcc 4.8 95 #endif 91 return (*creation_info.create_port_function)(creation_info); 96 92 } 97 93 else … … 102 98 }; 103 99 104 // for non-boundable types105 template <typename TWrapper, typename TBuffer, tPortImplementationType TYPE>106 struct tCheapCopyPortBaseImplementation<TWrapper, TBuffer, TYPE, false>107 {108 typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<TBuffer>, optimized::tCheapCopyPort>::type tPortBase;109 110 static core::tAbstractPort* CreatePort(tPortCreationInfo<TWrapper> creation_info)111 {112 creation_info.UnsetDefaultValue(); // TBuffer might differ from TWrapper => corrupts default value (it is set later in tPort)113 if (creation_info.BoundsSet())114 {115 FINROC_LOG_PRINT_STATIC(WARNING, "Bounds are not supported for type '", creation_info.data_type.GetName(), "'. Ignoring.");116 }117 return new tPortBase(creation_info);118 }119 };120 121 122 100 // standard cheap-copy implementation 123 101 template <typename T, tPortImplementationType TYPE> 124 102 struct tCheapCopyPortImplementation : 125 public tCheapCopyPortBaseImplementation<T, T, tPortImplementationType::CHEAP_COPY, IsBoundable<T>::value>103 public tCheapCopyPortBaseImplementation<T, tPortImplementationType::CHEAP_COPY> 126 104 { 127 105 typedef T tPortBuffer; … … 220 198 template <typename T> 221 199 struct tPortImplementation<T, tPortImplementationType::CHEAP_COPY_SINGLE_THREADED> : 222 public tCheapCopyPortBaseImplementation<T, T, tPortImplementationType::CHEAP_COPY_SINGLE_THREADED, IsBoundable<T>::value>200 public tCheapCopyPortBaseImplementation<T, tPortImplementationType::CHEAP_COPY_SINGLE_THREADED> 223 201 { 224 202 typedef api::tSingleThreadedCheapCopyPort<T> tPortBase; … … 289 267 static core::tAbstractPort* CreatePort(tPortCreationInfo<T>& pci) 290 268 { 291 if (pci.BoundsSet())292 {293 FINROC_LOG_PRINT_STATIC(WARNING, "Bounds are not supported for type '", pci.data_type.GetName(), "'. Ignoring.");294 }295 269 return new standard::tStandardPort(pci); 296 270 } -
common/tAbstractDataPortCreationInfo.cpp
r101 r155 37 37 // Internal includes with "" 38 38 //---------------------------------------------------------------------- 39 #include "plugins/data_ports/api/tBoundedPort.h" 40 #include "plugins/data_ports/numeric/tNumber.h" 39 41 40 42 //---------------------------------------------------------------------- … … 69 71 //---------------------------------------------------------------------- 70 72 73 namespace 74 { 75 76 struct tCreateBoundedPortFunctionRegister 77 { 78 rrlib::thread::tMutex mutex; 79 std::vector<std::pair<rrlib::rtti::tType, tAbstractDataPortCreationInfo::tCreatePortFunction>> functions; 80 81 tCreateBoundedPortFunctionRegister() 82 { 83 Add<unsigned char>(); 84 Add<signed char>(); 85 Add<char>(); 86 Add<short>(); 87 Add<unsigned short>(); 88 Add<int>(); 89 Add<unsigned int>(); 90 Add<long int>(); 91 Add<unsigned long int>(); 92 Add<long long int>(); 93 Add<unsigned long long int>(); 94 Add<size_t>(); 95 Add<float>(); 96 Add<double>(); 97 Add<rrlib::time::tDuration>(); 98 Add<numeric::tNumber>(); 99 } 100 101 template <typename T> 102 void Add() 103 { 104 functions.emplace_back(rrlib::rtti::tDataType<T>(), &api::tBoundedPort<T>::CreateInstance); 105 } 106 }; 107 108 tCreateBoundedPortFunctionRegister& CreateBoundedPortFunctionRegister() 109 { 110 static tCreateBoundedPortFunctionRegister function_register; 111 return function_register; 112 } 113 114 } 115 71 116 tAbstractDataPortCreationInfo::tAbstractDataPortCreationInfo() : 72 117 max_queue_size(-1), … … 77 122 name_set(false) 78 123 {} 124 125 void tAbstractDataPortCreationInfo::RegisterBoundedPortCreateFunction(const rrlib::rtti::tType& type, tCreatePortFunction function) 126 { 127 auto& function_register = CreateBoundedPortFunctionRegister(); 128 rrlib::thread::tLock lock(function_register.mutex); 129 for (auto & entry : function_register.functions) 130 { 131 if (entry.first == type) 132 { 133 return; 134 } 135 } 136 function_register.functions.emplace_back(type, function); 137 } 138 139 void tAbstractDataPortCreationInfo::SetBoundsGeneric(const rrlib::rtti::tGenericObject& min, const rrlib::rtti::tGenericObject& max, tOutOfBoundsAction out_of_bounds_action) 140 { 141 if (min.GetType() != max.GetType()) 142 { 143 throw std::invalid_argument("SetBoundsGeneric: min and max need the same type"); 144 } 145 146 bounds_type = min.GetType(); 147 size_t type_size = bounds_type.GetSize(); 148 bounds.resize(sizeof(size_t) + 3 * type_size + 7); // This will always be enough 149 memcpy(bounds.data(), &out_of_bounds_action, sizeof(size_t)); 150 memcpy(bounds.data() + sizeof(size_t), min.GetRawDataPointer(), type_size); 151 memcpy(bounds.data() + sizeof(size_t) + type_size, max.GetRawDataPointer(), type_size); 152 153 auto& function_register = CreateBoundedPortFunctionRegister(); 154 for (auto & entry : function_register.functions) 155 { 156 if (entry.first == bounds_type) 157 { 158 create_port_function = entry.second; 159 return; 160 } 161 } 162 RRLIB_LOG_PRINT(WARNING, "No function to create bounded port for type ", min.GetType(), " registered. Creating unbounded port."); 163 } 79 164 80 165 void tAbstractDataPortCreationInfo::SetString(const tString& s) -
common/tAbstractDataPortCreationInfo.h
r101 r155 55 55 namespace data_ports 56 56 { 57 58 //---------------------------------------------------------------------- 59 // Forward declarations / typedefs / enums 60 //---------------------------------------------------------------------- 61 62 namespace api 63 { 64 template <typename T> 65 class tBoundedPort; 66 } 67 57 68 namespace common 58 69 { 59 60 //---------------------------------------------------------------------- 61 // Forward declarations / typedefs / enums 62 //---------------------------------------------------------------------- 70 class tAbstractDataPort; 63 71 64 72 //---------------------------------------------------------------------- … … 93 101 tString config_entry; 94 102 103 /*! Custom create port function */ 104 typedef common::tAbstractDataPort* (*tCreatePortFunction)(const tAbstractDataPortCreationInfo&); 105 tCreatePortFunction create_port_function = nullptr; 106 95 107 /*! 96 108 * Creates port creation info with default values … … 100 112 101 113 /*! 114 * Registers create function for bounded port of type 'type' 115 */ 116 template <typename T> 117 static tCreatePortFunction RegisterBoundedPortCreateFunction() 118 { 119 RegisterBoundedPortCreateFunction(rrlib::rtti::tDataType<T>(), &api::tBoundedPort<T>::CreateInstance); 120 return &api::tBoundedPort<T>::CreateInstance; 121 } 122 123 /*! 102 124 * \return Have bounds for port been set? 103 125 */ 104 126 bool BoundsSet() const 105 127 { 106 return bounds. GetSize() > 0;128 return bounds.size(); 107 129 } 108 130 … … 116 138 117 139 /*! 118 * \return Bounds (when their exact type is not known at compile time) 119 */ 120 const rrlib::serialization::tConstSource&GetBoundsGeneric() const121 { 122 return bounds ;123 } 124 125 /*! 126 * \return Bounds (when theirexact type is not known at compile time)140 * \return Bounds (when their exact type is not known at compile time). nullptr if no bounds have been set 141 */ 142 const tBoundsBase* GetBoundsGeneric() const 143 { 144 return bounds.size() ? reinterpret_cast<const tBoundsBase*>(bounds.data()) : nullptr; 145 } 146 147 /*! 148 * \return Default (when its exact type is not known at compile time) 127 149 */ 128 150 const rrlib::serialization::tConstSource& GetDefaultGeneric() const … … 154 176 * \param out_of_bounds_action How to proceed if an incoming value is out of bounds 155 177 */ 156 void SetBoundsGeneric(const rrlib::rtti::tGenericObject& min, const rrlib::rtti::tGenericObject& max, 157 tOutOfBoundsAction out_of_bounds_action = tOutOfBoundsAction::ADJUST_TO_RANGE) 158 { 159 rrlib::serialization::tOutputStream stream(bounds); 160 // critical: needs to be the same serialization as used in tBounds 161 min.Serialize(stream); 162 max.Serialize(stream); 163 stream << out_of_bounds_action; 164 } 178 void SetBoundsGeneric(const rrlib::rtti::tGenericObject& min, const rrlib::rtti::tGenericObject& max, tOutOfBoundsAction out_of_bounds_action = tOutOfBoundsAction::ADJUST_TO_RANGE); 165 179 166 180 void SetDefaultGeneric(const rrlib::rtti::tGenericObject& default_val) … … 182 196 //---------------------------------------------------------------------- 183 197 protected: 198 199 template <typename T> 200 friend class data_ports::api::tBoundedPort; 184 201 185 202 /*! … … 210 227 211 228 /*! Storage for bounds */ 212 tStorage<300> bounds; 229 std::vector<unsigned char> bounds; 230 rrlib::rtti::tType bounds_type; 213 231 214 232 /*! Has name been set? (we do not check name for zero length, because ports without names may be created) */ … … 217 235 218 236 /*! 237 * Adds create function for bounded port of type 'type' 238 * 239 * \param type Port data type 240 * \param function Create function 241 */ 242 static void RegisterBoundedPortCreateFunction(const rrlib::rtti::tType& type, tCreatePortFunction function); 243 244 /*! 219 245 * Processes next string argument 220 246 */ -
tBounds.h
r77 r155 62 62 63 63 /*! How to proceed if an incoming value is out of bounds */ 64 enum class tOutOfBoundsAction 64 enum class tOutOfBoundsAction : size_t 65 65 { 66 66 DISCARD, //!< Discard incoming values that are out of bounds … … 69 69 }; 70 70 71 /*! Common base class for tBounds */ 72 class tBoundsBase 73 { 74 public: 75 76 /*! 77 * \return Action to perform when value is out of range 78 */ 79 inline tOutOfBoundsAction GetOutOfBoundsAction() const 80 { 81 return action; 82 } 83 84 protected: 85 86 /*! Action to perform when value is out of range */ 87 tOutOfBoundsAction action = tOutOfBoundsAction::DISCARD; 88 }; 89 71 90 //---------------------------------------------------------------------- 72 91 // Class declaration … … 81 100 */ 82 101 template <typename T> 83 class tBounds 102 class tBounds : public tBoundsBase 84 103 { 85 104 static_assert(IsBoundable<T>::value, "Type T is not boundable"); … … 98 117 tBounds(TMin min, TMax max, tOutOfBoundsAction out_of_bounds_action = tOutOfBoundsAction::ADJUST_TO_RANGE) : 99 118 min(min), max(max), 100 action(out_of_bounds_action),101 119 out_of_bounds_default() 102 120 { 121 this->action = out_of_bounds_action; 103 122 out_of_bounds_default = ToBounds(out_of_bounds_default); 104 123 } … … 112 131 tBounds(TMin min, TMax max, T out_of_bounds_default) : 113 132 min(min), max(max), 114 action(tOutOfBoundsAction::APPLY_DEFAULT),115 133 out_of_bounds_default(out_of_bounds_default) 116 134 { 135 this->action = tOutOfBoundsAction::APPLY_DEFAULT; 117 136 } 118 137 … … 139 158 { 140 159 return out_of_bounds_default; 141 }142 143 /*!144 * \return Action to perform when value is out of range145 */146 inline tOutOfBoundsAction GetOutOfBoundsAction() const147 {148 return action;149 160 } 150 161 … … 185 196 T min, max; 186 197 187 /*! Action to perform when value is out of range */188 tOutOfBoundsAction action;189 190 198 /*! Default value when value is out of bounds */ 191 199 T out_of_bounds_default; -
tPort.cpp
r128 r155 75 75 template class tPort<rrlib::serialization::tMemoryBuffer>; 76 76 77 template class api::tBoundedPort<uint8_t>; 78 template class api::tBoundedPort<int8_t>; 79 template class api::tBoundedPort<uint16_t>; 80 template class api::tBoundedPort<int16_t>; 81 template class api::tBoundedPort<uint32_t>; 82 template class api::tBoundedPort<int32_t>; 83 template class api::tBoundedPort<uint64_t>; 84 template class api::tBoundedPort<int64_t>; 85 template class api::tBoundedPort<float>; 86 template class api::tBoundedPort<double>; 87 template class api::tBoundedPort<numeric::tNumber>; 88 89 77 90 //---------------------------------------------------------------------- 78 91 // End of namespace declaration -
tPort.h
r154 r155 213 213 inline typename std::enable_if<AVAILABLE, tBounds<T>>::type GetBounds() const 214 214 { 215 typedef api::tBoundedPort<T , api::tPortImplementationTypeTrait<T>::type> tBoundedPort;215 typedef api::tBoundedPort<T> tBoundedPort; 216 216 if ((!GetWrapped()) || typeid(*GetWrapped()) != typeid(tBoundedPort)) 217 217 { … … 266 266 inline void SetBounds(const typename std::enable_if<AVAILABLE, tBounds<T>>::type& new_bounds) 267 267 { 268 typedef api::tBoundedPort<T , api::tPortImplementationTypeTrait<T>::type> tBoundedPort;268 typedef api::tBoundedPort<T> tBoundedPort; 269 269 if ((!GetWrapped()) || typeid(*GetWrapped()) != typeid(tBoundedPort)) 270 270 { … … 332 332 extern template class tPort<rrlib::serialization::tMemoryBuffer>; 333 333 334 extern template class api::tBoundedPort<uint8_t>; 335 extern template class api::tBoundedPort<int8_t>; 336 extern template class api::tBoundedPort<uint16_t>; 337 extern template class api::tBoundedPort<int16_t>; 338 extern template class api::tBoundedPort<uint32_t>; 339 extern template class api::tBoundedPort<int32_t>; 340 extern template class api::tBoundedPort<uint64_t>; 341 extern template class api::tBoundedPort<int64_t>; 342 extern template class api::tBoundedPort<float>; 343 extern template class api::tBoundedPort<double>; 344 extern template class api::tBoundedPort<numeric::tNumber>; 345 334 346 //---------------------------------------------------------------------- 335 347 // End of namespace declaration -
tPortCreationInfo.h
r145 r155 46 46 //---------------------------------------------------------------------- 47 47 #include "plugins/data_ports/common/tAbstractDataPortCreationInfo.h" 48 #include "plugins/data_ports/api/tBoundedPort.h" 48 49 49 50 //---------------------------------------------------------------------- … … 89 90 typename std::enable_if<AVAILABLE, tBounds<T>>::type GetBounds() const 90 91 { 92 if (BoundsSet()) 93 { 94 return *reinterpret_cast<const tBounds<T>*>(bounds.data()); 95 } 91 96 T t = T(); 92 tBounds<T> result(t, t); 93 if (!BoundsSet()) 94 { 95 FINROC_LOG_PRINT_STATIC(DEBUG_WARNING, "Bounds were not set"); 96 return result; 97 } 98 rrlib::serialization::tInputStream is(bounds); 99 is >> result; 100 return result; 97 return tBounds<T>(t, t); 101 98 } 102 99 … … 135 132 void Set(const typename std::enable_if<AVAILABLE, tBounds<T>>::type& bounds) 136 133 { 137 rrlib::serialization::tOutputStream os(this->bounds); 138 os << bounds; 134 this->bounds.resize(sizeof(tBounds<T>)); 135 memcpy(this->bounds.data(), &bounds, sizeof(tBounds<T>)); 136 create_port_function = tAbstractDataPortCreationInfo::RegisterBoundedPortCreateFunction<T>(); 137 this->bounds_type = rrlib::rtti::tDataType<T>(); 139 138 } 140 139 -
tests/test_collection.cpp
r143 r155 400 400 } 401 401 402 template <typename T> 403 void SetBoundsGeneric(T min, T max, tOutOfBoundsAction action) 404 { 405 common::tAbstractDataPortCreationInfo creation_info; 406 creation_info.name = "Bounds Test"; 407 creation_info.flags = cDEFAULT_INPUT_PORT_FLAGS; 408 creation_info.parent = &core::tRuntimeEnvironment::GetInstance(); 409 creation_info.data_type = rrlib::rtti::tDataType<T>(); 410 411 if (!std::is_arithmetic<T>::value) 412 { 413 common::tAbstractDataPortCreationInfo::RegisterBoundedPortCreateFunction<T>(); 414 } 415 416 rrlib::rtti::tGenericObjectWrapper<T> min_object(min); 417 rrlib::rtti::tGenericObjectWrapper<T> max_object(max); 418 creation_info.SetBoundsGeneric(min_object, max_object, action); 419 420 tGenericPort port(creation_info); 421 RRLIB_UNIT_TESTS_ASSERT(typeid(*port.GetWrapped()) == typeid(api::tBoundedPort<T>)); 422 api::tBoundedPort<T>& bounded_port = static_cast<api::tBoundedPort<T>&>(*port.GetWrapped()); 423 auto bounds = bounded_port.GetBounds(); 424 RRLIB_UNIT_TESTS_ASSERT(bounds.GetMin() == min); 425 RRLIB_UNIT_TESTS_ASSERT(bounds.GetMax() == max); 426 RRLIB_UNIT_TESTS_ASSERT(bounds.GetOutOfBoundsAction() == action); 427 port.ManagedDelete(); 428 } 429 402 430 class DataPortsTestCollection : public rrlib::util::tUnitTestSuite 403 431 { … … 431 459 TestHijackedPublishing<int>(42); 432 460 TestGenericPorts<bool>(true, false); 461 462 SetBoundsGeneric<uint8_t>(4, 9, tOutOfBoundsAction::ADJUST_TO_RANGE); 463 SetBoundsGeneric<int16_t>(-12, 900, tOutOfBoundsAction::APPLY_DEFAULT); 464 SetBoundsGeneric<int32_t>(-121, 5235623, tOutOfBoundsAction::DISCARD); 465 SetBoundsGeneric<int64_t>(-552121, 523511352456623, tOutOfBoundsAction::ADJUST_TO_RANGE); 466 SetBoundsGeneric<double>(-552121., 523511352456623, tOutOfBoundsAction::ADJUST_TO_RANGE); 467 SetBoundsGeneric<numeric::tNumber>(-552121., 523511352456623, tOutOfBoundsAction::ADJUST_TO_RANGE); 468 SetBoundsGeneric<std::pair<int, uint8_t>>(std::pair<int, uint8_t>(-44315, 90), std::pair<int, uint8_t>(-2, 177), tOutOfBoundsAction::APPLY_DEFAULT); 469 SetBoundsGeneric<std::array<short, 3>>({ -2, 5, 2}, { 5, -11233, 77 }, tOutOfBoundsAction::APPLY_DEFAULT); 470 SetBoundsGeneric<std::tuple<double, short, float>>(std::tuple<double, short, float>(-0.5, 1133, 0.11), std::tuple<double, short, float>(55, -1133, 6436.2), tOutOfBoundsAction::APPLY_DEFAULT); 433 471 } 434 472 -
type_traits.h
r138 r155 142 142 struct IsBoundable 143 143 { 144 enum { value = tIsCheaplyCopiedType<T>::value && HasSmallerThanOperator<T>::value && (!std::is_same<bool, T>::value) };144 enum { value = tIsCheaplyCopiedType<T>::value && HasSmallerThanOperator<T>::value && (!std::is_same<bool, T>::value) && rrlib::rtti::IsDefaultConstructionZeroMemory<T>::value }; 145 145 }; 146 146
Note: See TracChangeset
for help on using the changeset viewer.