1 /* 2 * 3 * Copyright (C) 2014-2019, OFFIS e.V. 4 * All rights reserved. See COPYRIGHT file for details. 5 * 6 * This software and supporting documentation were developed by 7 * 8 * OFFIS e.V. 9 * R&D Division Health 10 * Escherweg 2 11 * D-26121 Oldenburg, Germany 12 * 13 * 14 * Module: ofstd 15 * 16 * Author: Jan Schlamelcher 17 * 18 * Purpose: Implement fallback support for modern techniques defined 19 * in the STL's <utility> header (e.g. move semantics) 20 * for older compilers. 21 */ 22 23 #ifndef OFUTIL_H 24 #define OFUTIL_H 25 26 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ 27 28 #include "dcmtk/ofstd/oftraits.h" 29 #include "dcmtk/ofstd/oftypes.h" 30 31 /** @file ofutil.h 32 * Implement fallback support for modern techniques defined 33 * in the STL's <utility> header (e.g.\ move semantics) 34 * for older compilers. 35 */ 36 37 // -------------------- misc C++11 / non C++11 utils -------------------- 38 39 // The internet says <utility> should always be available, so we include 40 // it here to fix an issue with compilers that support std::tuple but 41 // not all of C++11 and perhaps other stuff. 42 #include <utility> 43 44 #ifdef HAVE_STL_TUPLE 45 #include <tuple> 46 #endif 47 48 #ifdef HAVE_CXX11 49 50 #define OFmove std::move 51 #define OFswap std::swap 52 53 // OFrvalue simply equals 'identity', as C++11 natively handles 54 // rvalues / prvalues and so on. 55 template<typename T> 56 using OFrvalue = T; 57 58 #define OFrvalue_ref(T) T&& 59 #define OFrvalue_access(RV) RV 60 #define OFrvalue_ref_upcast(T, RV) static_cast<T&&>(RV) 61 62 #else // fallback implementations 63 64 #ifndef DOXYGEN 65 66 // Meta-template to select the base class for OFrvalue 67 template<typename T,OFBool> 68 struct OFrvalue_storage 69 { 70 // Helper template to wrap types that we can't derive from, 71 // e.g. primitive types. 72 class type 73 { 74 public: 75 // copy constructor should be fine for primitive types. typeOFrvalue_storage76 inline type(const T& pt) 77 : t( pt ) {} typeOFrvalue_storage78 inline type(const OFrvalue_storage& rhs) 79 : t( rhs.pt ) {} 80 81 // automatic conversion to the underlying type 82 inline operator T&() const { return OFconst_cast( T&, t ); } 83 84 private: 85 // the actual object 86 T t; 87 }; 88 }; 89 90 // specialization for compound types 91 template<typename T> 92 struct OFrvalue_storage<T,OFTrue> 93 { 94 // simply use T itself as base 95 typedef T type; 96 }; 97 98 // SFINAE to detect if a type is derivable from 99 template<typename T> 100 class OFrvalue_base 101 { 102 // magic SFINAE stuff stolen from en.cppreference.com 103 struct no_type {}; 104 struct yes_type {double d;}; 105 template<typename X> 106 static yes_type sfinae(int X::*); 107 template<typename X> 108 static no_type sfinae(...); 109 110 public: 111 // employ SFINAE + template specialization to select 112 // the base type 113 typedef OFTypename OFrvalue_storage 114 < 115 T, 116 sizeof(sfinae<T>(OFnullptr)) == sizeof(yes_type) 117 >::type type; 118 }; 119 120 #endif // NOT DOXYGEN 121 122 /** A helper class to 'tag' objects as <i>rvalues</i> to help 123 * DCMTK's move emulation employed on pre C++11 compilers. 124 * @tparam T the base type an rvalue should be create of. 125 * @details OFrvalue wraps the type T inside a zero-overhead 126 * object employing T's move constructor when possible. 127 * @note When C++11 support is available, OFrvalue<T> will 128 * simply be a type alias for <i>T</i>, since a C++11 compiler 129 * handles rvalue reference conversions natively. 130 * @details 131 * <h2>Example</h2> 132 * This example describes how to move an object of type 133 * OFunique_ptr out of a function by using OFrvalue. 134 * @code 135 * OFrvalue<OFunique_ptr<DcmDataset> > getDataset() 136 * { 137 * return OFunique_ptr<DcmDataset>( new DcmDataset ); 138 * } 139 * . . . 140 * OFunique_ptr<DcmDataset> pDataset = getDataset(); 141 * @endcode 142 * @warning Some compilers might require you to use the following 143 * code instead, as older versions of the C++ standard allowed 144 * the compiler to use the copy constructor for binding an 145 * rvalue to an lvalue reference. 146 * Use this code template instead to achieve maximum portability: 147 * @code 148 * OFrvalue<OFunique_ptr<DcmDataset> > getDataset() 149 * { 150 * OFunique_ptr<DcmDataset> pDataset( new DcmDataset ); 151 * return OFmove( pDataset ); 152 * } 153 * @endcode 154 */ 155 template<typename T> 156 struct OFrvalue : OFrvalue_base<T>::type 157 { 158 #ifndef DOXYGEN 159 // allow to move construct from lvalue references 160 inline OFrvalue(const T& t) : OFrvalue_base<T>::type( *OFreinterpret_cast( const OFrvalue*, &t ) ) {} 161 // copy-construct from an rvalue reference 162 inline OFrvalue(const OFrvalue& rv) : OFrvalue_base<T>::type( rv ) {} 163 // poor man's in-place construction 164 template<typename X> 165 inline explicit OFrvalue( X x ) : OFrvalue_base<T>::type( x ) {} 166 template<typename X0,typename X1> 167 inline explicit OFrvalue( X0 x0, X1 x1 ) : OFrvalue_base<T>::type( x0, x1 ) {} 168 template<typename X0,typename X1,typename X2> 169 inline explicit OFrvalue( X0 x0, X1 x1, X2 x2 ) : OFrvalue_base<T>::type( x0, x1, x2 ) {} 170 #endif // NOT DOXYGEN 171 }; 172 173 #ifdef DOXYGEN 174 /** Determines <i>rvalue reference</i> type for the type <kbd>T</kbd>. 175 * @param T the base type to determine the rvalue reference type for. 176 * @note <i>OFrvalue_ref(T)</i> will expand to <kbd>T&&</kbd> when 177 * C++11 support is available. Otherwise DCMTK's move emulation will 178 * be used, employing an unspecified type to implement rvalue references. 179 * @details 180 * <h2>Example</h2> 181 * This example shows how to implement the <i>move constructor</i> and 182 * <i>move assignment</i> for a custom class in a portable fashion 183 * (employing C++11's native features when available and using DCMTK's 184 * move emulation otherwise). 185 * @code 186 * class MyMovable 187 * { 188 * public: 189 * MyMovable( OFrvalue_ref(MyMovable) rhs ) 190 * : m_hDatabase( rhs.m_hDatabase ) 191 * { 192 * // You need to use OFrvalue_access to get write access 193 * // to rvalue references when DCMTK's move emulation 194 * // is used. 195 * OFrvalue_access(rhs).m_hDatabase = OFnullptr; 196 * } 197 * 198 * MyMovable& operator=( OFrvalue_ref(MyMovable) rvrhs ) 199 * { 200 * // You may bind the rvalue reference to an lvalue 201 * // reference to ease access. 202 * MyMovable& rhs = OFrvalue_access(rvrhs); 203 * if( this != &rhs ) 204 * { 205 * disconnectDatabase( m_hDatabase ); 206 * m_hDatabase = rhs.m_hDatabase; 207 * rhs.m_hDatabase = OFnullptr; 208 * } 209 * return *this; 210 * } 211 * }; 212 * @endcode 213 */ 214 #define OFrvalue_ref(T) unspecified 215 216 /** Upcast an rvalue reference to an rvalue reference of one of its bases. 217 * This is a helper macro for being used with DCMTK's fallback implementation 218 * of move semantics. C++11 rvalue references should normally allow implicit 219 * upcasts, therefore, this macro typically has no effect if C++11 is enabled 220 * (it may be used to work around the behavior of older GCC versions). 221 * @param T the base class to upcast to 222 * @param RV the rvalue reference to upcast 223 */ 224 #define OFrvalue_ref_upcast(T, RV) unspecified 225 #else // NOT DOXYGEN 226 #define OFrvalue_ref(T) const OFrvalue<T >& 227 #define OFrvalue_ref_upcast(T, RV) OFmove<T >(RV) 228 #endif 229 230 /** Obtain an lvalue reference from an rvalue reference. 231 * DCMTK's move emulations does restrict write access to rvalue references 232 * due to compiler limitations. 233 * This method enables you to workaround this restriction by converting 234 * DCMTK's emulated rvalue references to lvalue references. 235 * @note Native rvalue references from C++11 don't need this workaround, 236 * therefore <i>OFrvalue_access</i> has no effect when C++11 support is 237 * available. 238 * @param rv an rvalue reference, e.g. the parameter of a <i>move constructor</i>. 239 */ 240 template<typename T> 241 T& OFrvalue_access( OFrvalue_ref(T) rv ) 242 { 243 #ifndef DOXYGEN 244 return OFconst_cast( OFrvalue<T>&, rv ); 245 #endif 246 } 247 248 /** Obtains an rvalue reference to its argument and converts it 249 * to an xvalue. OFmove is meant to 'mark' an object for a 250 * move operation, e.g. to move an OFVector object into another 251 * OFVector instance instead of copying it. 252 * @note OFmove will be an alias for std::move when native 253 * move semantics are supported (C++11 support is available). 254 * Otherwise DCMTK's move emulation will be used. This means 255 * you will have to specify rvalues (e.g. function return values) 256 * employing the OFrvalue class template. 257 * @param t The object to move. 258 * @see OFrvalue 259 * @see OFrvalue_ref 260 */ 261 template<typename T> 262 #ifndef DOXYGEN 263 OFrvalue<T>& OFmove( T& t ) 264 { 265 return *OFreinterpret_cast( OFrvalue<T>*, &t ); 266 } 267 268 template<typename T> 269 OFrvalue<T>& OFmove( OFrvalue<T>& rv ) 270 { 271 return rv; 272 } 273 274 template<typename T> 275 OFrvalue<T>& OFmove( const OFrvalue<T>& rv ) 276 { 277 return OFconst_cast( OFrvalue<T>&, rv ); 278 } 279 #else // NOT DOXYGEN 280 OFconstexpr xvalue OFmove( T< unspecified > t ); 281 #endif // DOXYGEN 282 283 /** Exchanges the given values. 284 * OFswap is an alias for std::swap if C++11 is supported. 285 * Otherwise OFswap simply creates a temporary copy of one 286 * argument to exchange both values. 287 * @note As intended for std::swap, there are some 288 * specializations for OFswap available, e.g. for OFoptional, 289 * which specializes OFswap to exchange optional objects 290 * more efficiently. When creating your own specializations 291 * for OFswap, make sure to specialize std::swap instead 292 * when C++11 support is available. 293 * @param t0 An object to be exchanged. 294 * @param t1 The object to be exchanged with t0. 295 */ 296 template<typename T> 297 void OFswap( T& t0, T& t1 ) 298 #ifndef DOXYGEN 299 { 300 T temp( OFmove( t0 ) ); 301 t0 = OFmove( t1 ); 302 t1 = OFmove( temp ); 303 } 304 #else // NOT DOXYGEN 305 ; 306 #endif // DOXYGEN 307 308 #endif // NOT C++11 309 310 // -------------------- STL pair -------------------- 311 312 #ifdef HAVE_STL_MAP 313 314 // Use native pair class, to be compatible to std::map 315 #define OFPair std::pair 316 #define OFMake_pair std::make_pair 317 318 #else // fallback implementation of std::pair 319 320 /** a pair - this implements parts of std::pair's interface. 321 */ 322 template<typename K, typename V> class OFPair 323 { 324 public: 325 326 /** this is the first value of the pair */ 327 K first; 328 329 /** this is the second value of the pair */ 330 V second; 331 332 /** default constructor */ 333 OFPair() : first(), second() { } 334 335 /** construct a OFPair for the two given values 336 * @param f the value for first. 337 * @param s the value for second. 338 */ 339 OFPair(const K& f, const V& s) : first(f), second(s) { } 340 341 /** copy constructor 342 * @param p Other OFPair to copy from. 343 */ 344 template<class OK, class OV> 345 OFPair(const OFPair<OK, OV>& p) : first(p.first), second(p.second) { } 346 347 /** copy constructor 348 * @param p Other OFPair to copy from. 349 */ 350 OFPair(const OFPair& p) : first(p.first), second(p.second) { } 351 352 /** assignment operator */ 353 OFPair<K, V>& operator=(const OFPair<K, V>& other) 354 { 355 first = other.first; 356 second = other.second; 357 return *this; 358 } 359 }; 360 361 /** helper function to create a pair. This is similar to std::make_pair() 362 * @param first the first part of the pair 363 * @param second the second art of the pair 364 * @relates OFPair 365 * @return the pair (first, second) 366 */ 367 template<typename K, typename V> 368 OFPair<K, V> OFMake_pair(const K& first, const V& second) 369 { 370 return OFPair<K, V>(first, second); 371 } 372 373 #endif // HAVE_STL_MAP - fallback implementation of OFPair 374 375 // -------------------- STL tuple -------------------- 376 377 #ifdef HAVE_STL_TUPLE 378 379 #ifdef HAVE_CXX11 380 381 template<std::size_t Index,typename T> 382 constexpr auto OFget( T&& t ) -> decltype( std::get<Index>( std::forward<T>( t ) ) ) 383 { 384 return std::get<Index>( std::forward<T>( t ) ); 385 } 386 387 template<typename X,typename T> 388 constexpr auto OFget( T&& t ) -> decltype( std::get<X>( std::forward<T>( t ) ) ) 389 { 390 return std::get<X>( std::forward<T>( t ) ); 391 } 392 393 template<typename Tuple> 394 using OFtuple_size = std::tuple_size<Tuple>; 395 396 template<std::size_t Index,typename Tuple> 397 using OFtuple_element = std::tuple_element<Index,Tuple>; 398 399 #else // HAVE_CXX11 400 401 template<typename Tuple> 402 struct OFtuple_size : STD_NAMESPACE tuple_size<Tuple> {}; 403 404 template<size_t Index,typename Tuple> 405 struct OFtuple_element : STD_NAMESPACE tuple_element<Index,Tuple> {}; 406 407 template<size_t Index,typename T> 408 OFTypename OFtuple_element<Index,T>::type OFget( T& t ) { return STD_NAMESPACE get<Index>( t ); } 409 410 template<size_t Index,typename T> 411 OFTypename OFtuple_element<Index,T>::type OFget( const T& t ) { return STD_NAMESPACE get<Index>( t ); } 412 413 #endif // NOT HAVE_CXX11 414 415 #else // HAVE_STL_TUPLE 416 417 template<typename Tuple> 418 struct OFtuple_size; 419 template<size_t Index,typename Tuple> 420 struct OFtuple_element; 421 422 // specialization of OFtuple_size for OFPair -> 2 423 template<typename K,typename V> 424 struct OFtuple_size<OFPair<K,V> > 425 : OFintegral_constant<size_t,2> {}; 426 427 // specialization of OFtuple_element for OFPair 428 // 0 -> K 429 template<typename K,typename V> 430 struct OFtuple_element<0,OFPair<K,V> > 431 { 432 typedef K type; 433 }; 434 435 // specialization of OFtuple_element for OFPair 436 // 1 -> V 437 template<typename K,typename V> 438 struct OFtuple_element<1,OFPair<K,V> > 439 { 440 typedef V type; 441 }; 442 443 // metafunction to apply OFget to OFPair 444 template<size_t Element> 445 struct OFpair_element; 446 447 // specialization for 0 -> first 448 template<> 449 struct OFpair_element<0> 450 { 451 template<typename K,typename V> 452 static K& from( OFPair<K,V>& p ) { return p.first; } 453 template<typename K,typename V> 454 static const K& from( const OFPair<K,V>& p ) { return p.first; } 455 }; 456 457 // specialization for 1 -> second 458 template<> 459 struct OFpair_element<1> 460 { 461 template<typename K,typename V> 462 static V& from( OFPair<K,V>& p ) { return p.second; } 463 template<typename K,typename V> 464 static const V& from( const OFPair<K,V>& p ) { return p.second; } 465 }; 466 467 // overload of OFget for OFPair, see above metafunction 'OFpair_element' 468 template<size_t Element,typename K,typename V> 469 typename OFtuple_element<Element,OFPair<K,V> >::type& OFget( OFPair<K,V>& p ) 470 { 471 return OFpair_element<Element>::from( p ); 472 } 473 474 // overload of OFget for const OFPair, see above metafunction 'OFpair_element' 475 template<size_t Element,typename K,typename V> 476 const typename OFtuple_element<Element,OFPair<K,V> >::type& OFget( const OFPair<K,V>& p ) 477 { 478 return OFpair_element<Element>::from( p ); 479 } 480 481 // tag to identify invalid OFtuple elements, needed for emulating 482 // variadic templates. 483 struct OFtuple_nil; 484 485 // include generated forward declaration for OFtuple. 486 #include "dcmtk/ofstd/variadic/tuplefwd.h" 487 488 #endif // HAVE_STL_TUPLE 489 490 #ifdef DOXYGEN // doxygen documentation of OFtuple utils 491 492 /** A metafunction to determine the size of a tuple. 493 * @tparam Tuple a tuple type, e.g. an instance of OFtuple. 494 * @pre Tuple is a tuple type, see @ref tuple_types "Tuple Types" 495 * for definition. 496 * @return OFtuple_size is derived from an appropriate instance of 497 * OFintegral_constant if the preconditions are met. This means 498 * OFtuple_size declares a static member constant <i>value</i> 499 * set to the tuple's size. 500 * @relates OFPair 501 * @relates OFtuple 502 * @details 503 * <h3>Usage Example:</h3> 504 * @code{.cpp} 505 * typedef OFtuple<OFString,size_t,OFVector<int> > MyTuple; 506 * typedef OFPair<OFString,MyTuple> MyPair; 507 * COUT << "OFtuple_size<MyTuple>::value: " << OFtuple_size<MyTuple>::value << OFendl; 508 * COUT << "OFtuple_size<MyPair>::value: " << OFtuple_size<MyPair>::value << OFendl; 509 * @endcode 510 * <b>Output:</b> 511 * @verbatim 512 OFtuple_size<MyTuple>::value: 3 513 OFtuple_size<MyPair>::value: 2 514 @endverbatim 515 * 516 */ 517 template<typename Tuple> 518 <metafunction> OFtuple_size; 519 520 /** A metafunction to determine the type of one element of a tuple. 521 * @tparam Index the index of the element its type should be determined. 522 * @tparam Tuple a tuple type, e.g. an instance of OFtuple. 523 * @pre Tuple is a tuple type, see @ref tuple_types "Tuple Types" 524 * for definition. 525 * @pre Index is a valid index , essentially: <kbd>Index < OFtuple_size<Tuple>::value</kbd>. 526 * @return if the preconditions are met, OFtuple_element declares a member 527 * type alias <i>type</i> that yields the type of the element at the given index. 528 * @relates OFtuple 529 * @details 530 * <h3>Usage Example:</h3> 531 * @code{.cpp} 532 * typedef OFPair<OFString,size_t> MyPair; 533 * typedef OFtuple<OFtuple_element<0,MyPair>::type,OFtuple_element<1,MyPair>::type> MyTuple; 534 * MyPair pair( "Hello World", 42 ); 535 * MyTuple tuple( pair ); // Works, since both elements' types are the same as within MyPair. 536 * @endcode 537 * 538 */ 539 template<size_t Index,typename Tuple> 540 <metafunction> OFtuple_element; 541 542 /** A function template to access an element of a tuple. 543 * @tparam Index the index of the element that should be accessed. 544 * @tparam Tuple a tuple type, e.g. an instance of OFtuple. This parameter 545 * is deduced automatically. 546 * @param tuple a reference to the tuple to access an element of. 547 * @pre Tuple is a tuple type, see @ref tuple_types "Tuple Types" 548 * for definition. 549 * @pre Index is a valid index , essentially: <kbd>Index < OFtuple_size<Tuple>::value</kbd>. 550 * @return a reference to the tuple's element at the given index. 551 * @relates OFtuple 552 * @details 553 * <h3>Usage Example:</h3> 554 * @code{.cpp} 555 * OFtuple<OFString,size_t,OFVector<int> > myTuple; 556 * OFget<0>( myTuple ) = "Hamish Alexander"; 557 * OFget<1>( myTuple ) = 23; 558 * OFget<2>( myTuple ).push_back( 42 ); 559 * @endcode 560 */ 561 template<size_t Index,typename Tuple> 562 typename OFtuple_element<Index,Tuple>::type& OFget( Tuple& tuple ); 563 564 /** A function template to access an element of a tuple. 565 * @tparam Index the index of the element that should be accessed. 566 * @tparam Tuple a tuple type, e.g. an instance of OFtuple. This parameter 567 * is deduced automatically. 568 * @param tuple a const reference to the tuple to access an element of. 569 * @pre Tuple is a tuple type, see @ref tuple_types "Tuple Types" 570 * for definition. 571 * @pre Index is a valid index , essentially: <kbd>Index < OFtuple_size<Tuple>::value</kbd>. 572 * @return a const reference to the tuple's element at the given index. 573 * @relates OFtuple 574 * @details 575 * <h3>Usage Example:</h3> 576 * @code{.cpp} 577 * const OFtuple<OFString,size_t,OFBool> myConstTuple( "Homer Simpson", 38, OFTrue ); 578 * if( OFget<0>( myConstTuple ) == "Homer Simpson" ) 579 * { 580 * // OFget<1>( myConstTuple ) = 23; INVALID, myConstTuple is const! 581 * OFBool isMale = OFget<2>( myConstTuple ); 582 * if( isMale ) 583 * COUT << OFget<0>( myConstTuple ) << ", age " 584 * << OFget<1>( myConstTuple ) << " is male." << OFendl; 585 * } 586 * @endcode 587 * <b>Output:</b> 588 * @verbatim 589 Homer Simpson, age 38 is male. 590 @endverbatim 591 */ 592 template<size_t Index,typename Tuple> 593 const typename OFtuple_element<Index,Tuple>::type& OFget( const Tuple& tuple ); 594 #endif // DOXYGEN 595 596 // -------------------- misc utils (OFinplace etc.) -------------------- 597 598 #ifndef DOXYGEN 599 600 // OFin_place hacks, look at the doxygen documentation instead if 601 // you know what's good for you! 602 class DCMTK_OFSTD_EXPORT OFin_place_tag { OFin_place_tag(); }; 603 typedef OFin_place_tag(&OFin_place_t)(); 604 #define OFin_place_type_t(T) OFin_place_tag(&)(T&) 605 #define OFin_place_index_t(I) OFin_place_tag(&)(OFintegral_constant<size_t,I>&) 606 DCMTK_OFSTD_EXPORT OFin_place_tag OFin_place(); 607 template<typename T> 608 OFin_place_tag OFin_place(T&) { return OFin_place(); } 609 template<size_t I> 610 OFin_place_tag OFin_place(OFintegral_constant<size_t,I>&) { return OFin_place(); } 611 612 #else // NOT DOXYGEN 613 614 /** @defgroup OFin_place_helpers_brief 615 * @details Tools for in-place construction of objects, e.g. certain OFvariant alternatives. 616 * @defgroup OFin_place_helpers Tools for in-place construction 617 * @details 618 * <b><em style="color:#7f0000">#include</em> <span class="keyword">"dcmtk/ofstd/ofutil.h"</span></b><br><br> 619 * @copydoc OFin_place_helpers_brief 620 * <table class="memberdecls"> 621 * <tr class="heading"> 622 * <td colspan="2"><div><h2 class="groupheader">Type Definitions</h2></div></td> 623 * </tr> 624 * <tr> 625 * <td class="memItemLeft" align="right" valign="top"><span class="keyword">typedef</span> <em style="color:#7f0000;opacity:.7">unspecified</em></td> 626 * <td class="memItemRight" valign="bottom"><a href="#OFin_place_t">OFin_place_t</a></td> 627 * </tr> 628 * <tr> 629 * <td class="mdescLeft"></td> 630 * <td class="mdescRight">A type for tagging an in-place constructor as such. <a href="#OFin_place_t">More...</a></td> 631 * </tr> 632 * <tr><td class="memSeparator" colspan="2"></td></tr> 633 * <tr><td class="memTemplParams" colspan="2">template<typename T></td></tr> 634 * <tr> 635 * <td class="memItemLeft" align="right" valign="top"><span class="keyword">typedef</span> <em style="color:#7f0000;opacity:.7">unspecified</em></td> 636 * <td class="memItemRight" valign="bottom"><a href="#OFin_place_type_t">OFin_place_type_t(T)</a></td> 637 * </tr> 638 * <tr> 639 * <td class="mdescLeft"></td> 640 * <td class="mdescRight">A type for tagging an in-place constructor for a certain type as such. <a href="#OFin_place_type_t">More...</a></td> 641 * </tr> 642 * <tr><td class="memSeparator" colspan="2"></td></tr> 643 * <tr><td class="memTemplParams" colspan="2">template<size_t I></td></tr> 644 * <tr> 645 * <td class="memItemLeft" align="right" valign="top"><span class="keyword">typedef</span> <em style="color:#7f0000;opacity:.7">unspecified</em></td> 646 * <td class="memItemRight" valign="bottom"><a href="#OFin_place_index_t">OFin_place_index_t(I)</a></td> 647 * </tr> 648 * <tr> 649 * <td class="mdescLeft"></td> 650 * <td class="mdescRight">A type for tagging an in-place constructor based on a certain index as such. <a href="#OFin_place_index_t">More...</a></td> 651 * </tr> 652 * <tr><td class="memSeparator" colspan="2"></td></tr> 653 * </table> 654 * <table class="memberdecls"> 655 * <tr class="heading"> 656 * <td colspan="2"><div><h2 class="groupheader">Global Constants</h2></div></td> 657 * </tr> 658 * <tr> 659 * <td class="memItemLeft" align="right" valign="top"><a href="#OFin_place_t">OFin_place_t</a></td> 660 * <td class="memItemRight" valign="bottom"><a href="#OFin_place_generic">OFin_place</a></td> 661 * </tr> 662 * <tr> 663 * <td class="mdescLeft"></td> 664 * <td class="mdescRight"> 665 * A constant of type <a href="#OFin_place_t">OFin_place_t</a> that may be used for in-place construction. 666 * <a href="#OFin_place_generic">More...</a> 667 * </td> 668 * </tr> 669 * <tr><td class="memSeparator" colspan="2"></td></tr> 670 * <tr><td class="memTemplParams" colspan="2">template<typename T></td></tr> 671 * <tr> 672 * <td class="memItemLeft" align="right" valign="top"><a href="#OFin_place_type_t">OFin_place_type_t(T)</a></td> 673 * <td class="memItemRight" valign="bottom"><a href="#OFin_place_type">OFin_place<T></a></td> 674 * </tr> 675 * <tr> 676 * <td class="mdescLeft"></td> 677 * <td class="mdescRight"> 678 * A constant of type <a href="#OFin_place_type_t">OFin_place_type_t(T)</a> that may be used for in-place construction. 679 * <a href="#OFin_place_type">More...</a> 680 * </td> 681 * </tr> 682 * <tr><td class="memSeparator" colspan="2"></td></tr> 683 * <tr><td class="memTemplParams" colspan="2">template<size_t I></td></tr> 684 * <tr> 685 * <td class="memItemLeft" align="right" valign="top"><a href="#OFin_place_index_t">OFin_place_index_t(I)</a></td> 686 * <td class="memItemRight" valign="bottom"><a href="#OFin_place_index">OFin_place<I></a></td> 687 * </tr> 688 * <tr> 689 * <td class="mdescLeft"></td> 690 * <td class="mdescRight"> 691 * A constant of type <a href="#OFin_place_index_t">OFin_place_index_t(I)</a> that may be used for in-place construction. 692 * <a href="#OFin_place_index">More...</a> 693 * </td> 694 * </tr> 695 * <tr><td class="memSeparator" colspan="2"></td></tr> 696 * </table> 697 * <h2 class="groupheader">Type Definition Documentation</h2> 698 * @anchor OFin_place_t 699 * <div class="memitem"> 700 * <div class="memproto"> 701 * <div class="memname"> 702 * <span class="keyword">typedef</span> <em style="color:#7f0000;opacity:.7">unspecified</em> OFin_place_t 703 * </div> 704 * </div> 705 * <div class="memdoc"> 706 * <br>A type for tagging an in-place constructor as such.<br> 707 * <dl></dl> 708 * <b>Usage Example:</b><br> 709 * @code{.cpp} 710 * template<typename T> 711 * class Wrapper 712 * { 713 * public: 714 * // Will copy construct the wrapped value from a T. 715 * Wrapper( const T& t ); 716 * 717 * // Will in-place construct the value from the given arguments, 718 * // calling T( arguments... ) internally, without unnecessary 719 * // copies. 720 * template<typename... Arguments> 721 * Wrapper( OFin_place_t, Arguments... arguments ); 722 * 723 * private: 724 * // ... wrapper implementation ... 725 * }; 726 * @endcode 727 * </div> 728 * </div> 729 * @anchor OFin_place_type_t 730 * <div class="memitem"> 731 * <div class="memproto"> 732 * <div class="memtemplate">template<typename T></div> 733 * <div class="memname"> 734 * <span class="keyword">typedef</span> <em style="color:#7f0000;opacity:.7">unspecified</em> OFin_place_type_t(T) 735 * </div> 736 * </div> 737 * <div class="memdoc"> 738 * <br>A type for tagging an in-place constructor for a certain type as such. 739 * <br> 740 * <dl class="tparams"> 741 * <dt>Template Parameters<dt> 742 * <dd><span class="paramname">T</span> the type this in-pace constructor handles, i.e. the type that will be constructed.</dd> 743 * </dl> 744 * @note Pre C++11 compilers do not support alias templates, therefore, OFin_place_type_t is implemented 745 * using preprocessor macros internally. This is why you need to use curved brackets instead of angled ones. 746 * 747 * <b>Usage Example:</b><br> 748 * @code{.cpp} 749 * template<typename A,typename B> 750 * class Union 751 * { 752 * public: 753 * // Will copy construct the wrapped value as an A from a. 754 * Union( const A& a ); 755 * 756 * // Will copy construct the wrapped value as a B from b. 757 * Union( const B& b ); 758 * 759 * // Will in-place construct the value as an A from the given 760 * // arguments, calling A( arguments... ) internally, without 761 * // unnecessary copies. 762 * template<typename... Arguments> 763 * Union( OFin_place_type_t(A), Arguments... arguments ); 764 * 765 * // Will in-place construct the value as a B from the given 766 * // arguments, calling B( arguments... ) internally, without 767 * // unnecessary copies. 768 * template<typename... Arguments> 769 * Union( OFin_place_type_t(B), Arguments... arguments ); 770 * 771 * private: 772 * // ... union implementation ... 773 * }; 774 * @endcode 775 * </div> 776 * </div> 777 * @anchor OFin_place_index_t 778 * <div class="memitem"> 779 * <div class="memproto"> 780 * <div class="memtemplate">template<size_t I></div> 781 * <div class="memname"> 782 * <span class="keyword">typedef</span> <em style="color:#7f0000;opacity:.7">unspecified</em> OFin_place_index_t(I) 783 * </div> 784 * </div> 785 * <div class="memdoc"> 786 * <br>A type for tagging an in-place constructor for a certain index as such.<br> 787 * <dl class="tparams"> 788 * <dt>Template Parameters<dt> 789 * <dd> 790 * <span class="paramname">I</span> the index this in-pace constructor handles, i.e. the zero 791 * based index of the type that will be constructed. 792 * </dd> 793 * </dl> 794 * @note Pre C++11 compilers do not support alias templates, therefore, OFin_place_index_t is implemented 795 * using preprocessor macros internally. This is why you need to use curved brackets instead of angled ones. 796 * 797 * <b>Usage Example:</b><br> 798 * @code{.cpp} 799 * template<typename A,typename B> 800 * class Union 801 * { 802 * public: 803 * // Will copy construct the wrapped value as an A from a. 804 * Union( const A& a ); 805 * 806 * // Will copy construct the wrapped value as a B from b. 807 * Union( const B& b ); 808 * 809 * // Will in-place construct the value as an A from the given 810 * // arguments, calling A( arguments... ) internally, without 811 * // unnecessary copies. 812 * // This will even work if A and B refer to the same type. 813 * template<typename... Arguments> 814 * Union( OFin_place_index_t(0), Arguments... arguments ); 815 * 816 * // Will in-place construct the value as a B from the given 817 * // arguments, calling B( arguments... ) internally, without 818 * // unnecessary copies. 819 * // This will even work if A and B refer to the same type. 820 * template<typename... Arguments> 821 * Union( OFin_place_index_t(1), Arguments... arguments ); 822 * 823 * private: 824 * // ... union implementation ... 825 * }; 826 * @endcode 827 * </div> 828 * </div> 829 * <h2 class="groupheader">Global Constant Documentation</h2> 830 * @anchor OFin_place_generic 831 * <div class="memitem"> 832 * <div class="memproto"> 833 * <div class="memname"> 834 * <a href="#OFin_place_t">OFin_place_t</a> OFin_place 835 * </div> 836 * </div> 837 * <div class="memdoc"> 838 * <br>A constant of type <a href="#OFin_place_t">OFin_place_t</a> that may be used for in-place construction.<br> 839 * @remarks OFin_place is actually an overloaded function, but instead of calling it 840 * (which one should never do), its address is used as a tag, since the type of 841 * its address differs depending on which overload and template parameters are used. 842 * See http://en.cppreference.com/w/cpp/utility/in_place for more information. 843 * 844 * <b>Usage Example:</b><br> 845 * @code{.cpp} 846 * template<typename T> 847 * class Wrapper; // see OFin_place_t example 848 * // ... 849 * // will construct an OFString and then copy construct the value in the wrapper 850 * Wrapper<OFString>( "Hello World" ); 851 * // will in-place construct the value in the wrapper 852 * Wrapper<OFString>( OFin_place, "Hello World" ); 853 * // this also works with multiple arguments: 854 * // will take only the fist five characters of the const char* 855 * Wrapper<OFString>( OFin_place, "Hello World", 5 ); 856 * @endcode 857 * </div> 858 * </div> 859 * @anchor OFin_place_type 860 * <div class="memitem"> 861 * <div class="memproto"> 862 * <div class="memtemplate">template<typename T></div> 863 * <div class="memname"> 864 * <a href="#OFin_place_type_t">OFin_place_type_t(T)</a> OFin_place<T> 865 * </div> 866 * </div> 867 * <div class="memdoc"> 868 * <br>A constant of type <a href="#OFin_place_type_t">OFin_place_type_t(T)</a> that may be used for in-place construction.<br> 869 * <dl class="tparams"> 870 * <dt>Template Parameters<dt> 871 * <dd><span class="paramname">T</span> the type for selecting an in-pace constructor, i.e. the type that will be constructed.</dd> 872 * </dl> 873 * @remarks OFin_place is actually an overloaded function, but instead of calling it 874 * (which one should never do), its address is used as a tag, since the type of 875 * its address differs depending on which overload and template parameters are used. 876 * See http://en.cppreference.com/w/cpp/utility/in_place for more information. 877 * 878 * <b>Usage Example:</b><br> 879 * @code{.cpp} 880 * template<typename A,typename B> 881 * class Union; // see OFin_place_type_t example 882 * // ... 883 * // will construct an OFString and then copy construct the value inside the union 884 * Union<int,OFString>( OFString( "Hello World" ) ); 885 * // will in-place construct an OFString value inside the union 886 * // with only the fist five characters 887 * Union<int,OFString>( OFin_place<OFString>, "Hello World", 5 ); 888 * // will construct an integer value inside the union by casting 889 * // the address of the character array constant to int 890 * Union<int,OFString>( OFin_place<int>, "Hello World" ); 891 * @endcode 892 * </div> 893 * </div> 894 * @anchor OFin_place_index 895 * <div class="memitem"> 896 * <div class="memproto"> 897 * <div class="memtemplate">template<size_t I></div> 898 * <div class="memname"> 899 * <a href="#OFin_place_index_t">OFin_place_index_t(I)</a> OFin_place<I> 900 * </div> 901 * </div> 902 * <div class="memdoc"> 903 * <br>A constant of type <a href="#OFin_place_index_t">OFin_place_index_t(I)</a> that may be used for in-place construction.<br> 904 * <dl class="tparams"> 905 * <dt>Template Parameters<dt> 906 * <dd> 907 * <span class="paramname">I</span> the index for selecting an in-pace constructor, i.e. the 908 * zero based index of the type that will be constructed. 909 * </dd> 910 * </dl> 911 * @remarks OFin_place is actually an overloaded function, but instead of calling it 912 * (which one should never do), its address is used as a tag, since the type of 913 * its address differs depending on which overload and template parameters are used. 914 * See http://en.cppreference.com/w/cpp/utility/in_place for more information. 915 * 916 * <b>Usage Example:</b><br> 917 * @code{.cpp} 918 * template<typename A,typename B> 919 * class Union; // see OFin_place_index_t example 920 * // ... 921 * // error, cannot determine which constructor shall be used, 922 * // since both take an int 923 * Union<int,int>( 3 ); 924 * // will in-place construct an int value inside the union 925 * // tagging it as an A 926 * Union<int,int>( OFin_place<0>, 3 ); 927 * // will in-place construct an int value inside the union 928 * // tagging it as a B 929 * Union<int,int>( OFin_place<1>, 3 ); 930 * @endcode 931 * </div> 932 * </div> 933 */ 934 935 #endif // DOXYGEN 936 937 #endif // OFUTIL_H 938