/* ** DO NOT EDIT THIS FILE !!! ** It was generated automatically by: ** ** User: jan ** Host: caesar ** Date: 2017-11-16 12:31:32 ** Prog: /home/jan/scripts/make_variadic.sh ** ** Purpose: ** Emulating variadic template parameters support for OFvariant with generated ** code. */ #ifndef VARIADIC_VARIANT_H #define VARIADIC_VARIANT_H #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/ofstd/variadic/helpers.h" #include "dcmtk/ofstd/ofutil.h" #include "dcmtk/ofstd/ofdiag.h" // We hide all this from doxygen, because it would only scare sane people // (and it is not needed for understanding how to use OFvariant). #ifndef DOXYGEN // Template recursively overload constructor and assignment operator for the // different alternatives of the variant (used in the template constructor/ // assignment members). template struct OFvariant_overload : OFvariant_overload { // Let the inherited methods take part in overload resolution using OFvariant_overload::copy_constructor; using OFvariant_overload::move_constructor; using OFvariant_overload::copy_assignment; using OFvariant_overload::move_assignment; static Uint16 test_accepts( T0 ); static Uint8 test_accepts( ... ); #ifdef OFalign static size_t copy_constructor( void* content, const T0& t0 ) { new (content) T0( t0 ); #else static size_t copy_constructor( void*& content, const T0& t0 ) { content = new T0( t0 ); #endif return Index; } #ifdef OFalign static size_t move_constructor( void* content, OFrvalue_ref(T0) t0 ) { new (content) T0( t0 ); #else static size_t move_constructor( void*& content, OFrvalue_ref(T0) t0 ) { content = new T0( t0 ); #endif return Index; } static bool copy_assignment( size_t index, void* content, const T0& t0 ) { if( index == Index ) { *static_cast( content ) = t0; return true; } return false; } static bool move_assignment( size_t index, void* content, OFrvalue_ref(T0) t0 ) { if( index == Index ) { *static_cast( content ) = t0; return true; } return false; } // This code is executed at compile-time, the warnings therefore make // absolutely no sense (only Visual Studio emits them ;-). // Converting an integer to a boolean value at compile-time won't have any // performance ramifications and type conversion will be checked elsewhere, // not when checking if an overload *potentially exists*. #include DCMTK_DIAGNOSTIC_PUSH #include DCMTK_DIAGNOSTIC_IGNORE_IMPLICIT_CONVERSION #include DCMTK_DIAGNOSTIC_IGNORE_VISUAL_STUDIO_PERFORMANCE_WARNING template struct accepts : OFintegral_constant::template accepts::value> {}; #include DCMTK_DIAGNOSTIC_POP }; // Template recursion end, declares both functions with incompatible // signatures so that the 'using' statements work but the functions // do not effectively take part in the overload resolution. template struct OFvariant_overload { static void copy_constructor(); static void move_constructor(); static void copy_assignment(); static void move_assignment(); template struct accepts : OFfalse_type {}; }; // Creates a function pointer lookup table to select a function for the // currently contained alternative based on the stored index. // This is not really magic, the syntax will hurt your eyes though! template class OFvariant_invoke_t { public: OFvariant_invoke_t() { // Template-recursively assign the function pointers to the fitting // position inside the function pointer array. This will most likely // be inlined by the compiler (it is tail recursive) and therefore // not hurt the performance. init<0>(); } OFTypename Invoker::return_type operator()( size_t index, void* content, const Invoker& invoker = Invoker() ) { // Select the fitting function pointer based on the index and call it with // the given pointer to the current contents. return (invoker.*m_Alternatives[index])( content ); } private: // This is the recursion step for the Init template, it initializes the current // function pointer and recurses to the Init template for the next index. template OFTypename OFenable_if<(Index < OFvariadic_parameter_pack_sizeof::value)>::type init() { m_Alternatives[Index] = &Invoker::template invoke::type>; init(); } // this is the specialization for the base of the recursion, doing nothing for the // N+1th alternative, effectively stopping the recursion. template OFTypename OFenable_if<(Index >= OFvariadic_parameter_pack_sizeof::value)>::type init() { } // the actual function pointer array OFTypename Invoker::return_type (Invoker::*m_Alternatives[OFvariadic_parameter_pack_sizeof::value])(void*) const; }; // A helper template function for initializing and using a function // pointer lookup table as dispatcher for variant visitation etc. template OFTypename Invoker::return_type OFvariant_invoke( size_t index, void* content, const Invoker& invoker = Invoker() ) { // this may be a race condition in older compilers, which is no // problem since the copied addresses of the functions are always // the same. static OFvariant_invoke_t invocation_table; return invocation_table( index, content, invoker ); } // A functor that does copy construction from another variant // object. struct OFvariant_copy_construct_invoker { typedef void return_type; #ifdef OFalign OFvariant_copy_construct_invoker( void* content ) : m_Content( content ) #else OFvariant_copy_construct_invoker( void*& content ) : m_pContent( content ) #endif { } template void invoke( void* content ) const { #ifdef OFalign new (m_Content) T( *static_cast( content ) ); #else m_pContent = new T( *static_cast( content ) ); #endif } #ifdef OFalign void* m_Content; #else void*& m_pContent; #endif }; // A functor that does move construction from another variant // object. struct OFvariant_move_construct_invoker { typedef void return_type; #ifdef OFalign OFvariant_move_construct_invoker( void* content ) : m_Content( content ) #else OFvariant_move_construct_invoker( void*& content ) : m_pContent( content ) #endif { } template void invoke( void* content ) const { #ifdef OFalign new (m_Content) T( OFmove( *static_cast( content ) ) ); #else m_pContent = new T( OFmove( *static_cast( content ) ) ); #endif } #ifdef OFalign void* m_Content; #else void*& m_pContent; #endif }; // A functor that copy assigns the contents of another variant // object that contains the same alternative (regarding the type). struct OFvariant_copy_assign_invoker { typedef void return_type; OFvariant_copy_assign_invoker( void* content ) : m_Content( content ) { } template void invoke( void* rhs ) const { *static_cast( m_Content ) = *static_cast( rhs ); } void* m_Content; }; // A functor that move assigns the contents of another variant // object that contains the same alternative (regarding the type). struct OFvariant_move_assign_invoker { typedef void return_type; OFvariant_move_assign_invoker( void* content ) : m_Content( content ) { } template void invoke( void* rhs ) const { *static_cast( m_Content ) = OFmove( *static_cast( rhs ) ); } void* m_Content; }; // A functor that destroys the contained object. struct OFvariant_destroy_invoker { typedef void return_type; template void invoke( void* content ) const { #ifdef OFalign static_cast( content )->~T(); #else delete static_cast( content ); #endif } }; // A functor that invokes the given functor, seriously! template struct OFvariant_visit_invoker { typedef ReturnType return_type; OFvariant_visit_invoker( FN& fn ) : m_Fn( fn ) { } template ReturnType invoke( void* content ) const { return m_Fn( *static_cast( content ) ); } FN& m_Fn; }; // The same as above, but for the const case. template struct OFvariant_const_visit_invoker { typedef ReturnType return_type; OFvariant_const_visit_invoker( FN& fn ) : m_Fn( fn ) { } template ReturnType invoke( void* content ) const { return m_Fn( *static_cast( content ) ); } FN& m_Fn; }; // The actual variant implementation. Don't mess with this, look // at the doxygen API description instead. template class OFvariant { public: // typedef for old compilers that do not define the type 'OFvariant' in derived classes typedef OFvariant variant; OFvariant() #ifdef OFalign : m_Content() #else : m_pContent( new T0 ) #endif , m_Index( 0 ) { #ifdef OFalign new (content()) T0; #endif } template OFvariant( const T& t, OFTypename OFenable_if::template accepts::value,int>::type = 0 ) #ifdef OFalign : m_Content() #else : m_pContent() #endif , m_Index( OFvariant_overload<0,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>::copy_constructor( content(), t ) ) { } template OFvariant( OFrvalue_ref(T) t, OFTypename OFenable_if::template accepts >::value,int>::type = 0 ) #ifdef OFalign : m_Content() #else : m_pContent() #endif , m_Index( OFvariant_overload<0,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>::move_constructor( content(), t ) ) { } OFvariant( const OFvariant& rhs ) #ifdef OFalign : m_Content() #else : m_pContent() #endif , m_Index( rhs.index() ) { copy_construct( rhs.content() ); } OFvariant( OFrvalue_ref(OFvariant) rhs ) #ifdef OFalign : m_Content() #else : m_pContent() #endif , m_Index( rhs.index() ) { move_construct( rhs.content() ); } template OFTypename OFenable_if::template accepts::value,OFvariant>::type& operator=( const T& t ) { // Either assign 't' if the contained alternative fits. if( !OFvariant_overload<0,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>::copy_assignment( index(), content(), t ) ) { // Or destroy the contained alternative and construct // a new one, based on 't'. destroy(); m_Index = OFvariant_overload<0,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>::copy_constructor( content(), t ); } return *this; } template OFTypename OFenable_if::template accepts >::value,OFvariant>::type& operator=( OFrvalue_ref(T) t ) { // Either assign 't' if the contained alternative fits. if( !OFvariant_overload<0,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>::move_assignment( index(), content(), t ) ) { // Or destroy the contained alternative and construct // a new one, based on 't'. destroy(); m_Index = OFvariant_overload<0,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>::move_constructor( content(), t ); } return *this; } OFvariant& operator=( const OFvariant& rhs ) { if( this != &rhs ) { // Do 'native' assignment if both variants contain // the same alternative if( m_Index == rhs.m_Index ) { OFvariant_invoke ( m_Index, rhs.content(), OFvariant_copy_assign_invoker( content() ) ); } else { // Destroy the contents and copy construct a new // one destroy(); m_Index = rhs.m_Index; copy_construct( rhs.content() ); } } return *this; } OFvariant& operator=( OFrvalue_ref(OFvariant) rhs ) { if( this != &rhs ) { // Do 'native' assignment if both variants contain // the same alternative if( m_Index == rhs.m_Index ) { OFvariant_invoke ( m_Index, rhs.content(), OFvariant_move_assign_invoker( content() ) ); } else { // Destroy the contents and copy construct a new // one destroy(); m_Index = rhs.m_Index; move_construct( rhs.content() ); } } return *this; } ~OFvariant() { // Destroy the contained object destroy(); } size_t index() const { // Well, this is easy return m_Index; } private: // Friend declarations for visitation and get<>. template friend T* OFget( OFvariant* ); template friend const T* OFget( const OFvariant* ); template friend ReturnType OFvisit( FN, OFvariant& ); template friend ReturnType OFvisit( FN, const OFvariant& ); // Invoke copy construction void copy_construct( void* rhs ) { OFvariant_invoke ( m_Index, rhs, OFvariant_copy_construct_invoker( content() ) ); } // Invoke move construction void move_construct( void* rhs ) { OFvariant_invoke ( m_Index, rhs, OFvariant_move_construct_invoker( content() ) ); } // Invoke destructor void destroy() { OFvariant_invoke( m_Index, content() ); } #ifdef OFalign // Allocate content with alignment. typedef OFTypename OFfold::type max_sizeof_type; typedef OFTypename OFfold::type max_alignof_type; void* content() const { return m_Content; } mutable OFalign_typename(Uint8[max_sizeof_type::value],max_alignof_type::value) m_Content; #else // Allocate content on the heap. void*& content() const { return OFconst_cast(void*&,m_pContent); } void* m_pContent; #endif size_t m_Index; }; // Actual implementation of get<> by type. template T* OFget( OFvariant* v ) { return v->index() == OFvariadic_find_type::value ? static_cast( v->content() ) : OFnullptr ; } // The same as above, but for the const case. template const T* OFget( const OFvariant* v ) { return v->index() == OFvariadic_find_type::value ? static_cast( v->content() ) : OFnullptr ; } // Actual implementation if variant visitation. template ReturnType OFvisit( FN fn, OFvariant& v ) { return OFvariant_invoke,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>( v.index(), v.content(), OFvariant_visit_invoker( fn ) ); } // The same as above, but for the const case. template ReturnType OFvisit( FN fn, const OFvariant& v ) { return OFvariant_invoke,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49>( v.index(), v.content(), OFvariant_const_visit_invoker( fn ) ); } #endif // !DOXYGEN #endif // VARIADIC_VARIANT_H