Mercurial > hg > vamp-build-and-test
view DEPENDENCIES/generic/include/boost/flyweight/key_value.hpp @ 60:01e6213c3f91
Merge
author | Chris Cannam |
---|---|
date | Fri, 12 Sep 2014 08:17:00 +0100 |
parents | 2665513ce2d3 |
children | c530137014c0 |
line wrap: on
line source
/* Copyright 2006-2008 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See http://www.boost.org/libs/flyweight for library home page. */ #ifndef BOOST_FLYWEIGHT_KEY_VALUE_HPP #define BOOST_FLYWEIGHT_KEY_VALUE_HPP #if defined(_MSC_VER)&&(_MSC_VER>=1200) #pragma once #endif #include <boost/flyweight/detail/value_tag.hpp> #include <boost/flyweight/key_value_fwd.hpp> #include <boost/mpl/assert.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/type_traits/aligned_storage.hpp> #include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/is_same.hpp> #include <new> /* key-value policy: flywewight lookup is based on Key, which also serves * to construct Value only when needed (new factory entry). key_value is * used to avoid the construction of temporary values when such construction * is expensive. * Optionally, KeyFromValue extracts the key from a value, which * is needed in expressions like this: * * typedef flyweight<key_value<Key,Value> > fw_t; * fw_t fw; * Value v; * fw=v; // no key explicitly given * * If no KeyFromValue is provided, this latter expression fails to compile. */ namespace boost{ namespace flyweights{ namespace detail{ template<typename Key,typename Value,typename KeyFromValue> struct optimized_key_value:value_marker { typedef Key key_type; typedef Value value_type; class rep_type { public: /* template ctors */ #define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type #define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \ :value_ptr(0) \ { \ new(spc_ptr())key_type(BOOST_PP_ENUM_PARAMS(n,t)); \ } #include <boost/flyweight/detail/perfect_fwd.hpp> rep_type(const value_type& x):value_ptr(&x){} rep_type(const rep_type& x):value_ptr(x.value_ptr) { if(!x.value_ptr)new(key_ptr())key_type(*x.key_ptr()); } ~rep_type() { if(!value_ptr) key_ptr()->~key_type(); else if(value_cted())value_ptr->~value_type(); } operator const key_type&()const { if(value_ptr)return key_from_value(*value_ptr); else return *key_ptr(); } operator const value_type&()const { /* This is always called after construct_value() or copy_value(), * so we access spc directly rather than through value_ptr to * save us an indirection. */ return *static_cast<value_type*>(spc_ptr()); } private: friend struct optimized_key_value; void* spc_ptr()const{return static_cast<void*>(&spc);} bool value_cted()const{return value_ptr==spc_ptr();} key_type* key_ptr()const { return static_cast<key_type*>(static_cast<void*>(&spc)); } static const key_type& key_from_value(const value_type& x) { KeyFromValue k; return k(x); } void construct_value()const { if(!value_cted()){ /* value_ptr must be ==0, oherwise copy_value would have been called */ key_type k(*key_ptr()); key_ptr()->~key_type(); value_ptr= /* guarantees key won't be re-dted at ~rep_type if the */ static_cast<value_type*>(spc_ptr())+1; /* next statement throws */ value_ptr=new(spc_ptr())value_type(k); } } void copy_value()const { if(!value_cted())value_ptr=new(spc_ptr())value_type(*value_ptr); } mutable typename boost::aligned_storage< (sizeof(key_type)>sizeof(value_type))? sizeof(key_type):sizeof(value_type), (boost::alignment_of<key_type>::value > boost::alignment_of<value_type>::value)? boost::alignment_of<key_type>::value: boost::alignment_of<value_type>::value >::type spc; mutable const value_type* value_ptr; }; static void construct_value(const rep_type& r) { r.construct_value(); } static void copy_value(const rep_type& r) { r.copy_value(); } }; template<typename Key,typename Value> struct regular_key_value:value_marker { typedef Key key_type; typedef Value value_type; class rep_type { public: /* template ctors */ #define BOOST_FLYWEIGHT_PERFECT_FWD_NAME explicit rep_type #define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \ :key(BOOST_PP_ENUM_PARAMS(n,t)),value_ptr(0){} #include <boost/flyweight/detail/perfect_fwd.hpp> rep_type(const value_type& x):key(no_key_from_value_failure()){} rep_type(const rep_type& x):key(x.key),value_ptr(0){} ~rep_type() { if(value_ptr)value_ptr->~value_type(); } operator const key_type&()const{return key;} operator const value_type&()const { /* This is always called after construct_value(),so we access spc * directly rather than through value_ptr to save us an indirection. */ return *static_cast<value_type*>(spc_ptr()); } private: friend struct regular_key_value; void* spc_ptr()const{return static_cast<void*>(&spc);} struct no_key_from_value_failure { BOOST_MPL_ASSERT_MSG( false, NO_KEY_FROM_VALUE_CONVERSION_PROVIDED, (key_type,value_type)); operator const key_type&()const; }; void construct_value()const { if(!value_ptr)value_ptr=new(spc_ptr())value_type(key); } key_type key; mutable typename boost::aligned_storage< sizeof(value_type), boost::alignment_of<value_type>::value >::type spc; mutable const value_type* value_ptr; }; static void construct_value(const rep_type& r) { r.construct_value(); } static void copy_value(const rep_type&){} }; } /* namespace flyweights::detail */ template<typename Key,typename Value,typename KeyFromValue> struct key_value: mpl::if_< is_same<KeyFromValue,no_key_from_value>, detail::regular_key_value<Key,Value>, detail::optimized_key_value<Key,Value,KeyFromValue> >::type {}; } /* namespace flyweights */ } /* namespace boost */ #endif