bug fixes

This commit is contained in:
Daniel Larimer 2015-02-27 16:07:50 -05:00
parent c0a4ed77b1
commit f9f965809b
3 changed files with 209 additions and 175 deletions

View file

@ -538,7 +538,7 @@ namespace fc {
pack_static_variant( Stream& s ):stream(s){} pack_static_variant( Stream& s ):stream(s){}
typedef void result_type; typedef void result_type;
template<typename T> void operator()( const T& v ) template<typename T> void operator()( const T& v )const
{ {
pack( stream, v ); pack( stream, v );
} }
@ -551,7 +551,7 @@ namespace fc {
unpack_static_variant( Stream& s ):stream(s){} unpack_static_variant( Stream& s ):stream(s){}
typedef void result_type; typedef void result_type;
template<typename T> void operator()( T& v ) template<typename T> void operator()( T& v )const
{ {
unpack( stream, v ); unpack( stream, v );
} }
@ -561,8 +561,8 @@ namespace fc {
template<typename Stream, typename... T> template<typename Stream, typename... T>
void pack( Stream& s, const static_variant<T...>& sv ) void pack( Stream& s, const static_variant<T...>& sv )
{ {
pack( sv, unsigned_int(s.which()) ); pack( s, unsigned_int(sv.which()) );
s.visit( pack_static_variant<Stream>(sv) ); sv.visit( pack_static_variant<Stream>(s) );
} }
template<typename Stream, typename... T> void unpack( Stream& s, static_variant<T...>& sv ) template<typename Stream, typename... T> void unpack( Stream& s, static_variant<T...>& sv )

View file

@ -26,231 +26,265 @@ struct position;
template<typename... Ts> template<typename... Ts>
struct type_info; struct type_info;
template<typename StaticVariant>
struct copy_construct
{
StaticVariant& sv;
copy_construct( StaticVariant& s ):sv(s){}
template<typename T>
void operator()( const T& v )const
{
sv.init(v);
}
};
template<int N, typename T, typename... Ts> template<int N, typename T, typename... Ts>
struct storage_ops<N, T&, Ts...> { struct storage_ops<N, T&, Ts...> {
static void del(int n, void *data) {} static void del(int n, void *data) {}
static void con(int n, void *data) {} static void con(int n, void *data) {}
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, void *data, visitor& v) {} static typename visitor::result_type apply(int n, void *data, visitor& v) {}
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, void *data, const visitor& v) {} static typename visitor::result_type apply(int n, void *data, const visitor& v) {}
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, visitor& v) {} static typename visitor::result_type apply(int n, const void *data, visitor& v) {}
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {} static typename visitor::result_type apply(int n, const void *data, const visitor& v) {}
}; };
template<int N, typename T, typename... Ts> template<int N, typename T, typename... Ts>
struct storage_ops<N, T, Ts...> { struct storage_ops<N, T, Ts...> {
static void del(int n, void *data) { static void del(int n, void *data) {
if(n == N) reinterpret_cast<T*>(data)->~T(); if(n == N) reinterpret_cast<T*>(data)->~T();
else storage_ops<N + 1, Ts...>::del(n, data); else storage_ops<N + 1, Ts...>::del(n, data);
} }
static void con(int n, void *data) { static void con(int n, void *data) {
if(n == N) new(reinterpret_cast<T*>(data)) T(); if(n == N) new(reinterpret_cast<T*>(data)) T();
else storage_ops<N + 1, Ts...>::del(n, data); else storage_ops<N + 1, Ts...>::del(n, data);
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, void *data, visitor& v) { static typename visitor::result_type apply(int n, void *data, visitor& v) {
if(n == N) return v(*reinterpret_cast<T*>(data)); if(n == N) return v(*reinterpret_cast<T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v); else return storage_ops<N + 1, Ts...>::apply(n, data, v);
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, void *data, const visitor& v) { static typename visitor::result_type apply(int n, void *data, const visitor& v) {
if(n == N) return v(*reinterpret_cast<T*>(data)); if(n == N) return v(*reinterpret_cast<T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v); else return storage_ops<N + 1, Ts...>::apply(n, data, v);
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, visitor& v) { static typename visitor::result_type apply(int n, const void *data, visitor& v) {
if(n == N) return v(*reinterpret_cast<const T*>(data)); if(n == N) return v(*reinterpret_cast<const T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v); else return storage_ops<N + 1, Ts...>::apply(n, data, v);
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, const visitor& v) { static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
if(n == N) return v(*reinterpret_cast<const T*>(data)); if(n == N) return v(*reinterpret_cast<const T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v); else return storage_ops<N + 1, Ts...>::apply(n, data, v);
} }
}; };
template<int N> template<int N>
struct storage_ops<N> { struct storage_ops<N> {
static void del(int n, void *data) { static void del(int n, void *data) {
throw std::runtime_error( throw std::runtime_error(
"Internal error: static_variant tag is invalid." "Internal error: static_variant tag is invalid."
); );
} }
static void con(int n, void *data) { static void con(int n, void *data) {
throw std::runtime_error( throw std::runtime_error(
"Internal error: static_variant tag is invalid." "Internal error: static_variant tag is invalid."
); );
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, void *data, visitor& v) { static typename visitor::result_type apply(int n, void *data, visitor& v) {
throw std::runtime_error( throw std::runtime_error(
"Internal error: static_variant tag is invalid." "Internal error: static_variant tag is invalid."
); );
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, void *data, const visitor& v) { static typename visitor::result_type apply(int n, void *data, const visitor& v) {
throw std::runtime_error( throw std::runtime_error(
"Internal error: static_variant tag is invalid." "Internal error: static_variant tag is invalid."
); );
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, visitor& v) { static typename visitor::result_type apply(int n, const void *data, visitor& v) {
throw std::runtime_error( throw std::runtime_error(
"Internal error: static_variant tag is invalid." "Internal error: static_variant tag is invalid."
); );
} }
template<typename visitor> template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, const visitor& v) { static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
throw std::runtime_error( throw std::runtime_error(
"Internal error: static_variant tag is invalid." "Internal error: static_variant tag is invalid."
); );
} }
}; };
template<typename X> template<typename X>
struct position<X> { struct position<X> {
static const int pos = -1; static const int pos = -1;
}; };
template<typename X, typename... Ts> template<typename X, typename... Ts>
struct position<X, X, Ts...> { struct position<X, X, Ts...> {
static const int pos = 0; static const int pos = 0;
}; };
template<typename X, typename T, typename... Ts> template<typename X, typename T, typename... Ts>
struct position<X, T, Ts...> { struct position<X, T, Ts...> {
static const int pos = position<X, Ts...>::pos != -1 ? position<X, Ts...>::pos + 1 : -1; static const int pos = position<X, Ts...>::pos != -1 ? position<X, Ts...>::pos + 1 : -1;
}; };
template<typename T, typename... Ts> template<typename T, typename... Ts>
struct type_info<T&, Ts...> { struct type_info<T&, Ts...> {
static const bool no_reference_types = false; static const bool no_reference_types = false;
static const bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates; static const bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
static const size_t size = type_info<Ts...>::size > sizeof(T&) ? type_info<Ts...>::size : sizeof(T&); static const size_t size = type_info<Ts...>::size > sizeof(T&) ? type_info<Ts...>::size : sizeof(T&);
}; };
template<typename T, typename... Ts> template<typename T, typename... Ts>
struct type_info<T, Ts...> { struct type_info<T, Ts...> {
static const bool no_reference_types = type_info<Ts...>::no_reference_types; static const bool no_reference_types = type_info<Ts...>::no_reference_types;
static const bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates; static const bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
static const size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&); static const size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&);
}; };
template<> template<>
struct type_info<> { struct type_info<> {
static const bool no_reference_types = true; static const bool no_reference_types = true;
static const bool no_duplicates = true; static const bool no_duplicates = true;
static const size_t size = 0; static const size_t size = 0;
}; };
} // namespace impl } // namespace impl
template<typename... Types> template<typename... Types>
class static_variant { class static_variant {
static_assert(impl::type_info<Types...>::no_reference_types, "Reference types are not permitted in static_variant."); static_assert(impl::type_info<Types...>::no_reference_types, "Reference types are not permitted in static_variant.");
static_assert(impl::type_info<Types...>::no_duplicates, "static_variant type arguments contain duplicate types."); static_assert(impl::type_info<Types...>::no_duplicates, "static_variant type arguments contain duplicate types.");
int tag; int _tag;
char storage[impl::type_info<Types...>::size]; char storage[impl::type_info<Types...>::size];
static_variant() = delete; template<typename X>
void init(const X& x) {
template<typename X> _tag = impl::position<X, Types...>::pos;
void init(const X& x) { new(storage) X(x);
tag = impl::position<X, Types...>::pos; }
new(storage) X(x);
} template<typename StaticVariant>
friend struct copy_construct;
public: public:
template<typename X> template<typename X>
static_variant(const X& v) { struct tag
static_assert( {
impl::position<X, Types...>::pos != -1, static_assert(
"Type not in static_variant." impl::position<X, Types...>::pos != -1,
); "Type not in static_variant."
init(v); );
} static const int value = impl::position<X, Types...>::pos;
~static_variant() { };
impl::storage_ops<0, Types...>::del(tag, storage); static_variant()
} {
template<typename X> impl::storage_ops<0, Types...>::con(0, storage);
void operator=(const X& v) { }
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
this->~static_variant();
init(v);
}
template<typename X>
X& get() {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(tag == impl::position<X, Types...>::pos) {
return *reinterpret_cast<X*>(storage);
} else {
throw std::runtime_error(
std::string("static_variant does not contain value of type ") + typeid(X).name()
);
}
}
template<typename X>
const X& get() const {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(tag == impl::position<X, Types...>::pos) {
return *reinterpret_cast<const X*>(storage);
} else {
throw std::runtime_error(
std::string("static_variant does not contain value of type ") + typeid(X).name()
);
}
}
template<typename visitor>
typename visitor::result_type visit(visitor& v) {
return impl::storage_ops<0, Types...>::apply(tag, storage, v);
}
template<typename visitor> template<typename... Other>
typename visitor::result_type visit(const visitor& v) { static_variant( const static_variant<Other...>& cpy )
return impl::storage_ops<0, Types...>::apply(tag, storage, v); {
} cpy.apply( impl::copy_construct<static_variant<Types...>>(*this) );
}
template<typename visitor> template<typename X>
typename visitor::result_type visit(visitor& v)const { static_variant(const X& v) {
return impl::storage_ops<0, Types...>::apply(tag, storage, v); static_assert(
} impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
init(v);
}
~static_variant() {
impl::storage_ops<0, Types...>::del(_tag, storage);
}
template<typename X>
void operator=(const X& v) {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
this->~static_variant();
init(v);
}
template<typename X>
X& get() {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(_tag == impl::position<X, Types...>::pos) {
return *reinterpret_cast<X*>(storage);
} else {
throw std::runtime_error(
std::string("static_variant does not contain value of type ") + typeid(X).name()
);
}
}
template<typename X>
const X& get() const {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(_tag == impl::position<X, Types...>::pos) {
return *reinterpret_cast<const X*>(storage);
} else {
throw std::runtime_error(
std::string("static_variant does not contain value of type ") + typeid(X).name()
);
}
}
template<typename visitor>
typename visitor::result_type visit(visitor& v) {
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
}
template<typename visitor> template<typename visitor>
typename visitor::result_type visit(const visitor& v)const { typename visitor::result_type visit(const visitor& v) {
return impl::storage_ops<0, Types...>::apply(tag, storage, v); return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
} }
void set_which( int w ) { template<typename visitor>
this->~static_variant(); typename visitor::result_type visit(visitor& v)const {
impl::storage_ops<0, Types...>::con(tag, storage); return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
} }
int which() const {return tag;}
template<typename visitor>
typename visitor::result_type visit(const visitor& v)const {
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
}
void set_which( int w ) {
this->~static_variant();
impl::storage_ops<0, Types...>::con(_tag, storage);
}
int which() const {return _tag;}
}; };
template<typename Result> template<typename Result>
struct visitor { struct visitor {
typedef Result result_type; typedef Result result_type;
}; };
} // namespace fc } // namespace fc

View file

@ -508,7 +508,7 @@ namespace fc
from_static_variant( variant& dv ):var(dv){} from_static_variant( variant& dv ):var(dv){}
typedef void result_type; typedef void result_type;
template<typename T> void operator()( const T& v ) template<typename T> void operator()( const T& v )const
{ {
to_variant( v, var ); to_variant( v, var );
} }
@ -520,7 +520,7 @@ namespace fc
to_static_variant( const variant& dv ):var(dv){} to_static_variant( const variant& dv ):var(dv){}
typedef void result_type; typedef void result_type;
template<typename T> void operator()( T& v ) template<typename T> void operator()( T& v )const
{ {
to_variant( var, v ); to_variant( var, v );
} }