bug fixes
This commit is contained in:
parent
c0a4ed77b1
commit
f9f965809b
3 changed files with 209 additions and 175 deletions
|
|
@ -538,7 +538,7 @@ namespace fc {
|
|||
pack_static_variant( Stream& s ):stream(s){}
|
||||
|
||||
typedef void result_type;
|
||||
template<typename T> void operator()( const T& v )
|
||||
template<typename T> void operator()( const T& v )const
|
||||
{
|
||||
pack( stream, v );
|
||||
}
|
||||
|
|
@ -551,7 +551,7 @@ namespace fc {
|
|||
unpack_static_variant( Stream& s ):stream(s){}
|
||||
|
||||
typedef void result_type;
|
||||
template<typename T> void operator()( T& v )
|
||||
template<typename T> void operator()( T& v )const
|
||||
{
|
||||
unpack( stream, v );
|
||||
}
|
||||
|
|
@ -561,8 +561,8 @@ namespace fc {
|
|||
template<typename Stream, typename... T>
|
||||
void pack( Stream& s, const static_variant<T...>& sv )
|
||||
{
|
||||
pack( sv, unsigned_int(s.which()) );
|
||||
s.visit( pack_static_variant<Stream>(sv) );
|
||||
pack( s, unsigned_int(sv.which()) );
|
||||
sv.visit( pack_static_variant<Stream>(s) );
|
||||
}
|
||||
|
||||
template<typename Stream, typename... T> void unpack( Stream& s, static_variant<T...>& sv )
|
||||
|
|
|
|||
|
|
@ -26,231 +26,265 @@ struct position;
|
|||
template<typename... Ts>
|
||||
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>
|
||||
struct storage_ops<N, T&, Ts...> {
|
||||
static void del(int n, void *data) {}
|
||||
static void con(int n, void *data) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {}
|
||||
static void del(int n, void *data) {}
|
||||
static void con(int n, void *data) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {}
|
||||
};
|
||||
|
||||
template<int N, typename T, typename... Ts>
|
||||
struct storage_ops<N, T, Ts...> {
|
||||
static void del(int n, void *data) {
|
||||
if(n == N) reinterpret_cast<T*>(data)->~T();
|
||||
else storage_ops<N + 1, Ts...>::del(n, data);
|
||||
}
|
||||
static void con(int n, void *data) {
|
||||
if(n == N) new(reinterpret_cast<T*>(data)) T();
|
||||
else storage_ops<N + 1, Ts...>::del(n, data);
|
||||
}
|
||||
static void del(int n, void *data) {
|
||||
if(n == N) reinterpret_cast<T*>(data)->~T();
|
||||
else storage_ops<N + 1, Ts...>::del(n, data);
|
||||
}
|
||||
static void con(int n, void *data) {
|
||||
if(n == N) new(reinterpret_cast<T*>(data)) T();
|
||||
else storage_ops<N + 1, Ts...>::del(n, data);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<const T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<const T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<const T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<const T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct storage_ops<N> {
|
||||
static void del(int n, void *data) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
static void con(int n, void *data) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
static void del(int n, void *data) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
static void con(int n, void *data) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
|
||||
throw std::runtime_error(
|
||||
"Internal error: static_variant tag is invalid."
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename X>
|
||||
struct position<X> {
|
||||
static const int pos = -1;
|
||||
static const int pos = -1;
|
||||
};
|
||||
|
||||
template<typename X, typename... Ts>
|
||||
struct position<X, X, Ts...> {
|
||||
static const int pos = 0;
|
||||
static const int pos = 0;
|
||||
};
|
||||
|
||||
template<typename X, typename T, typename... 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>
|
||||
struct type_info<T&, Ts...> {
|
||||
static const bool no_reference_types = false;
|
||||
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 bool no_reference_types = false;
|
||||
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&);
|
||||
};
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct type_info<T, Ts...> {
|
||||
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 size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&);
|
||||
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 size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct type_info<> {
|
||||
static const bool no_reference_types = true;
|
||||
static const bool no_duplicates = true;
|
||||
static const size_t size = 0;
|
||||
static const bool no_reference_types = true;
|
||||
static const bool no_duplicates = true;
|
||||
static const size_t size = 0;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template<typename... Types>
|
||||
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_duplicates, "static_variant type arguments contain duplicate types.");
|
||||
|
||||
int tag;
|
||||
char storage[impl::type_info<Types...>::size];
|
||||
|
||||
static_variant() = delete;
|
||||
|
||||
template<typename X>
|
||||
void init(const X& x) {
|
||||
tag = impl::position<X, Types...>::pos;
|
||||
new(storage) X(x);
|
||||
}
|
||||
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.");
|
||||
|
||||
int _tag;
|
||||
char storage[impl::type_info<Types...>::size];
|
||||
|
||||
template<typename X>
|
||||
void init(const X& x) {
|
||||
_tag = impl::position<X, Types...>::pos;
|
||||
new(storage) X(x);
|
||||
}
|
||||
|
||||
template<typename StaticVariant>
|
||||
friend struct copy_construct;
|
||||
public:
|
||||
template<typename X>
|
||||
static_variant(const X& 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 X>
|
||||
struct tag
|
||||
{
|
||||
static_assert(
|
||||
impl::position<X, Types...>::pos != -1,
|
||||
"Type not in static_variant."
|
||||
);
|
||||
static const int value = impl::position<X, Types...>::pos;
|
||||
};
|
||||
static_variant()
|
||||
{
|
||||
impl::storage_ops<0, Types...>::con(0, storage);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
typename visitor::result_type visit(const visitor& v) {
|
||||
return impl::storage_ops<0, Types...>::apply(tag, storage, v);
|
||||
}
|
||||
template<typename... Other>
|
||||
static_variant( const static_variant<Other...>& cpy )
|
||||
{
|
||||
cpy.apply( impl::copy_construct<static_variant<Types...>>(*this) );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
typename visitor::result_type visit(visitor& v)const {
|
||||
return impl::storage_ops<0, Types...>::apply(tag, storage, v);
|
||||
}
|
||||
template<typename X>
|
||||
static_variant(const X& 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>
|
||||
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 visitor>
|
||||
typename visitor::result_type visit(const visitor& v) {
|
||||
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
typename visitor::result_type visit(visitor& v)const {
|
||||
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
|
||||
}
|
||||
|
||||
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>
|
||||
struct visitor {
|
||||
typedef Result result_type;
|
||||
typedef Result result_type;
|
||||
};
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -508,7 +508,7 @@ namespace fc
|
|||
from_static_variant( variant& dv ):var(dv){}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
|
@ -520,7 +520,7 @@ namespace fc
|
|||
to_static_variant( const variant& dv ):var(dv){}
|
||||
|
||||
typedef void result_type;
|
||||
template<typename T> void operator()( T& v )
|
||||
template<typename T> void operator()( T& v )const
|
||||
{
|
||||
to_variant( var, v );
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue