any.hpp
Go to the documentation of this file.
00001 //
00002 // Copyright (c) 2016 Martin Moene
00003 //
00004 // https://github.com/martinmoene/any-lite
00005 //
00006 // This code is licensed under the MIT License (MIT).
00007 //
00008 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00009 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00010 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00011 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00012 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00013 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00014 // THE SOFTWARE.
00015 
00016 #pragma once
00017 
00018 #ifndef NONSTD_ANY_LITE_HPP
00019 #define NONSTD_ANY_LITE_HPP
00020 
00021 #include <typeinfo>
00022 #include <utility>
00023 
00024 #define  any_lite_VERSION "0.0.0"
00025 
00026 // any-lite configuration:
00027 
00028 // any-lite alignment configuration:
00029 
00030 // Compiler detection (C++17 is speculative):
00031 
00032 #define any_CPP11_OR_GREATER  ( __cplusplus >= 201103L )
00033 #define any_CPP14_OR_GREATER  ( __cplusplus >= 201402L )
00034 #define any_CPP17_OR_GREATER  ( __cplusplus >= 201700L )
00035 
00036 // half-open range [lo..hi):
00037 #define any_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
00038 
00039 #if defined(_MSC_VER) && !defined(__clang__)
00040 # define any_COMPILER_MSVC_VERSION   (_MSC_VER / 100 - 5 - (_MSC_VER < 1900))
00041 #else
00042 # define any_COMPILER_MSVC_VERSION   0
00043 #endif
00044 
00045 #if defined __GNUC__
00046 # define any_COMPILER_GNUC_VERSION  __GNUC__
00047 #else
00048 # define any_COMPILER_GNUC_VERSION    0
00049 #endif
00050 
00051 // Presence of C++11 language features:
00052 
00053 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 10
00054 # define any_HAVE_NULLPTR  1
00055 #endif
00056 
00057 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 12
00058 # define any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG  1
00059 # define any_HAVE_INITIALIZER_LIST  1
00060 #endif
00061 
00062 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 14
00063 # define any_HAVE_CONSTEXPR_11  1
00064 # define any_HAVE_NOEXCEPT  1
00065 #endif
00066 
00067 // Presence of C++14 language features:
00068 
00069 #if any_CPP14_OR_GREATER
00070 # define any_HAVE_CONSTEXPR_14  1
00071 #endif
00072 
00073 // Presence of C++17 language features:
00074 
00075 // Presence of C++ library features:
00076 
00077 #if any_COMPILER_GNUC_VERSION
00078 # define any_HAVE_TR1_TYPE_TRAITS  1
00079 # define any_HAVE_TR1_ADD_CONST  1
00080 # define any_HAVE_TR1_REMOVE_REFERENCE  1
00081 #endif
00082 
00083 #if any_CPP11_OR_GREATER || any_COMPILER_MSVC_VERSION >= 9
00084 # define any_HAVE_TYPE_TRAITS  1
00085 # define any_HAVE_STD_ADD_CONST  1
00086 # define any_HAVE_STD_REMOVE_REFERENCE  1
00087 #endif
00088 
00089 // For the rest, consider VC14 as C++11 for any-lite:
00090 
00091 #if any_COMPILER_MSVC_VERSION >= 14
00092 # undef  any_CPP11_OR_GREATER
00093 # define any_CPP11_OR_GREATER  1
00094 #endif
00095 
00096 // C++ feature usage:
00097 
00098 #if any_HAVE_CONSTEXPR_11
00099 # define any_constexpr constexpr
00100 #else
00101 # define any_constexpr /*constexpr*/
00102 #endif
00103 
00104 #if any_HAVE_CONSTEXPR_14
00105 # define any_constexpr14 constexpr
00106 #else
00107 # define any_constexpr14 /*constexpr*/
00108 #endif
00109 
00110 #if any_HAVE_NOEXCEPT
00111 # define any_noexcept noexcept
00112 #else
00113 # define any_noexcept /*noexcept*/
00114 #endif
00115 
00116 #if any_HAVE_NULLPTR
00117 # define any_nullptr nullptr
00118 #else
00119 # define any_nullptr NULL
00120 #endif
00121 
00122 // additional includes:
00123 
00124 #if ! any_HAVE_NULLPTR
00125 # include <cstddef>
00126 #endif
00127 
00128 #if any_HAVE_INITIALIZER_LIST
00129 # include <initializer_list>
00130 #endif
00131 
00132 #if any_HAVE_TYPE_TRAITS
00133 # include <type_traits>
00134 #elif any_HAVE_TR1_TYPE_TRAITS
00135 # include <tr1/type_traits>
00136 #endif
00137 
00138 //
00139 // in_place: code duplicated in any-lite, optional-lite, variant-lite:
00140 //
00141 
00142 #if ! nonstd_lite_HAVE_IN_PLACE_TYPES
00143 
00144 namespace nonstd {
00145 
00146 namespace detail {
00147 
00148 template< class T >
00149 struct in_place_type_tag {};
00150 
00151 template< std::size_t I >
00152 struct in_place_index_tag {};
00153 
00154 } // namespace detail
00155 
00156 struct in_place_t {};
00157 
00158 template< class T >
00159 inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
00160 {
00161     return in_place_t();
00162 }
00163 
00164 template< std::size_t I >
00165 inline in_place_t in_place( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() )
00166 {
00167     return in_place_t();
00168 }
00169 
00170 // mimic templated typedef:
00171 
00172 #define nonstd_lite_in_place_type_t( T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
00173 #define nonstd_lite_in_place_index_t(T)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<I> )
00174 
00175 #define nonstd_lite_HAVE_IN_PLACE_TYPES  1
00176 
00177 } // namespace nonstd
00178 
00179 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
00180 
00181 //
00182 // any:
00183 //
00184 
00185 namespace nonstd {  namespace any_lite {
00186 
00187 namespace detail {
00188 
00189 // C++11 emulation:
00190 
00191 #if any_HAVE_STD_ADD_CONST
00192 
00193 using std::add_const;
00194 
00195 #elif any_HAVE_TR1_ADD_CONST
00196 
00197 using std::tr1::add_const;
00198 
00199 #else
00200 
00201 template< class T > struct add_const { typedef const T type; };
00202 
00203 #endif // any_HAVE_ADD_CONST
00204 
00205 #if any_HAVE_STD_REMOVE_REFERENCE
00206 
00207 using std::remove_reference;
00208 
00209 #elif any_HAVE_TR1_REMOVE_REFERENCE
00210 
00211 using std::tr1::remove_reference;
00212 
00213 #else
00214 
00215 template< class T > struct remove_reference     { typedef T type; };
00216 template< class T > struct remove_reference<T&> { typedef T type; };
00217 
00218 #endif // any_HAVE_STD_REMOVE_REFERENCE
00219 
00220 } // namespace detail
00221 
00222 class bad_any_cast : public std::bad_cast
00223 {
00224 public:
00225 #if any_CPP11_OR_GREATER
00226     virtual const char* what() const any_noexcept
00227 #else
00228     virtual const char* what() const throw()
00229 #endif
00230    {
00231       return "any-lite: bad any_cast";
00232    }
00233 };
00234 
00235 class any
00236 {
00237 public:
00238     any_constexpr any() any_noexcept
00239     : content( any_nullptr )
00240     {}
00241 
00242     any( any const & rhs )
00243     : content( rhs.content ? rhs.content->clone() : any_nullptr )
00244     {}
00245 
00246 #if any_CPP11_OR_GREATER
00247 
00248     any( any && rhs ) any_noexcept
00249     : content( std::move( rhs.content ) )
00250     {
00251         rhs.content = any_nullptr;
00252     }
00253 
00254     template< class ValueType, class T = typename std::decay<ValueType>::type, typename = typename std::enable_if< ! std::is_same<T, any>::value >::type >
00255     any( ValueType && value ) any_noexcept
00256     : content( new holder<T>( std::forward<ValueType>( value ) ) )
00257     {}
00258 
00259     template< class T, class... Args, typename = typename std::enable_if< std::is_constructible<T, Args...>::value >::type >
00260     explicit any( nonstd_lite_in_place_type_t(T), Args&&... args )
00261     : content( new holder<T>( T( std::forward<Args>(args)... ) ) )
00262     {}
00263 
00264     template< class T, class U, class... Args, typename = typename std::enable_if< std::is_constructible<T, std::initializer_list<U>&, Args...>::value >::type >
00265     explicit any( nonstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
00266     : content( new holder<T>( T( il, std::forward<Args>(args)... ) ) )
00267     {}
00268 
00269 #else
00270 
00271     template< class ValueType >
00272     any( ValueType const & value )
00273     : content( new holder<ValueType>( value ) )
00274     {}
00275 
00276 #endif // any_CPP11_OR_GREATER
00277 
00278     ~any()
00279     {
00280         reset();
00281     }
00282 
00283     any & operator=( any const & rhs )
00284     {
00285         any( rhs ).swap( *this );
00286         return *this;
00287     }
00288 
00289 #if any_CPP11_OR_GREATER
00290 
00291     any & operator=( any && rhs ) any_noexcept
00292     {
00293         any( std::move( rhs ) ).swap( *this );
00294         return *this;
00295     }
00296 
00297     template< class ValueType, class T = typename std::decay<ValueType>::type, typename = typename std::enable_if< ! std::is_same<T, any>::value >::type >
00298     any & operator=( ValueType && rhs )
00299     {
00300         any( std::forward<ValueType>( rhs ) ).swap( *this );
00301         return *this;
00302     }
00303 
00304     template< class T, class... Args >
00305     void emplace( Args && ... args )
00306     {
00307         any( T( std::forward<Args>(args)... ) ).swap( *this );
00308     }
00309 
00310     template< class T, class U, class... Args, typename = typename std::enable_if< std::is_constructible<T, std::initializer_list<U>&, Args...>::value >::type >
00311     void emplace( std::initializer_list<U> il, Args&&... args )
00312     {
00313         any( T( il, std::forward<Args>(args)... ) ).swap( *this );
00314     }
00315 
00316 #else
00317 
00318     template< class ValueType >
00319     any & operator=( ValueType const & rhs )
00320     {
00321         any( rhs ).swap( *this );
00322         return *this;
00323     }
00324 
00325 #endif // any_CPP11_OR_GREATER
00326 
00327     void reset() any_noexcept
00328     {
00329         delete content; content = any_nullptr;
00330     }
00331 
00332     void swap( any & rhs ) any_noexcept
00333     {
00334         std::swap( content, rhs.content );
00335     }
00336 
00337     bool has_value() const any_noexcept
00338     {
00339         return content != any_nullptr;
00340     }
00341 
00342     const std::type_info & type() const any_noexcept
00343     {
00344         return has_value() ? content->type() : typeid( void );
00345     }
00346 
00347     //
00348     // non-standard:
00349     //
00350 
00351     template< class ValueType >
00352     const ValueType * to_ptr() const
00353     {
00354         return &( static_cast<holder<ValueType> *>( content )->held );
00355     }
00356 
00357     template< class ValueType >
00358     ValueType * to_ptr()
00359     {
00360         return &( static_cast<holder<ValueType> *>( content )->held );
00361     }
00362 
00363 private:
00364     class placeholder
00365     {
00366     public:
00367         virtual ~placeholder()
00368         {
00369         }
00370 
00371         virtual std::type_info const & type() const = 0;
00372 
00373         virtual placeholder * clone() const = 0;
00374     };
00375 
00376     template< typename ValueType >
00377     class holder : public placeholder
00378     {
00379     public:
00380         holder( ValueType const & value )
00381         : held( value )
00382         {}
00383 
00384 #if any_CPP11_OR_GREATER
00385         holder( ValueType && value )
00386         : held( std::move( value ) )
00387         {}
00388 #endif
00389 
00390         virtual std::type_info const & type() const
00391         {
00392             return typeid( ValueType );
00393         }
00394 
00395         virtual placeholder * clone() const
00396         {
00397             return new holder( held );
00398         }
00399 
00400         ValueType held;
00401     };
00402 
00403     placeholder * content;
00404 };
00405 
00406 inline void swap( any & x, any & y ) any_noexcept
00407 {
00408     x.swap( y );
00409 }
00410 
00411 #if any_CPP11_OR_GREATER
00412 
00413 template< class T, class ...Args >
00414 inline any make_any( Args&& ...args )
00415 {
00416     return any( in_place<T>, std::forward<Args>(args)...);
00417 }
00418 
00419 template< class T, class U, class ...Args >
00420 inline any make_any( std::initializer_list<U> il, Args&& ...args )
00421 {
00422     return any( in_place<T>, il, std::forward<Args>(args)...);
00423 }
00424 
00425 #endif // any_CPP11_OR_GREATER
00426 
00427 #if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
00428 template< class ValueType, typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type >
00429 #else
00430 template< class ValueType >
00431 #endif
00432 inline ValueType any_cast( any const & operand )
00433 {
00434    const ValueType * result = any_cast< typename detail::add_const< typename detail::remove_reference<ValueType>::type >::type >( &operand );
00435 
00436    if ( ! result )
00437    {
00438       throw bad_any_cast();
00439    }
00440 
00441    return *result;
00442 }
00443 
00444 #if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
00445 template< class ValueType, typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type >
00446 #else
00447 template< class ValueType >
00448 #endif
00449 inline ValueType any_cast( any & operand )
00450 {
00451    const ValueType * result = any_cast< typename detail::remove_reference<ValueType>::type >( &operand );
00452 
00453    if ( ! result )
00454    {
00455       throw bad_any_cast();
00456    }
00457 
00458    return *result;
00459 }
00460 
00461 #if any_CPP11_OR_GREATER
00462 
00463 #if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
00464 template< class ValueType, typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type >
00465 #else
00466 template< class ValueType >
00467 #endif
00468 inline ValueType any_cast( any && operand )
00469 {
00470    const ValueType * result = any_cast< typename detail::remove_reference<ValueType>::type >( &operand );
00471 
00472    if ( ! result )
00473    {
00474       throw bad_any_cast();
00475    }
00476 
00477    return *result;
00478 }
00479 
00480 #endif // any_CPP11_OR_GREATER
00481 
00482 template< class ValueType >
00483 inline ValueType const * any_cast( any const * operand ) any_noexcept
00484 {
00485     return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
00486 }
00487 
00488 template<class ValueType >
00489 inline ValueType * any_cast( any * operand ) any_noexcept
00490 {
00491     return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
00492 }
00493 
00494 } // namespace any_lite
00495 
00496 using namespace any_lite;
00497 
00498 } // namespace nonstd
00499 
00500 #endif // NONSTD_ANY_LITE_HPP


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:55