mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Don't rely on typeid() naming in VariantArray
This commit is contained in:
@@ -34,7 +34,22 @@ namespace {
|
|||||||
inline T dispatch_get_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, const IfcParse::declaration* entity_or_type, uint8_t index_)
|
inline T dispatch_get_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, const IfcParse::declaration* entity_or_type, uint8_t index_)
|
||||||
{
|
{
|
||||||
if (storage_model_ == 0) {
|
if (storage_model_ == 0) {
|
||||||
return array_.storage_ptr->get<T>(index_);
|
try {
|
||||||
|
return array_.storage_ptr->get<T>(index_);
|
||||||
|
} catch (const impl::storage_type_mismatch& e) {
|
||||||
|
throw IfcParse::IfcException(
|
||||||
|
// entity_or_type not passed, but in v0.9 this is beginning to make sense
|
||||||
|
(entity_or_type
|
||||||
|
? std::string("On instance #" + std::to_string(instance_name_) + " of " + entity_or_type->name() + ": ")
|
||||||
|
: std::string("")) +
|
||||||
|
"Requested type <" + e.requested() + "> does not match actual type <" + e.actual() + "> at index " + std::to_string(index_));
|
||||||
|
} catch (const std::out_of_range& e) {
|
||||||
|
throw IfcParse::IfcException(
|
||||||
|
(entity_or_type
|
||||||
|
? std::string("On instance #" + std::to_string(instance_name_) + " of " + entity_or_type->name() + ": ")
|
||||||
|
: std::string("")) +
|
||||||
|
e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef IFOPSH_WITH_ROCKSDB
|
#ifdef IFOPSH_WITH_ROCKSDB
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -72,6 +72,83 @@ class IFC_PARSE_API Derived {};
|
|||||||
class IFC_PARSE_API empty_aggregate_t {};
|
class IFC_PARSE_API empty_aggregate_t {};
|
||||||
class IFC_PARSE_API empty_aggregate_of_aggregate_t {};
|
class IFC_PARSE_API empty_aggregate_of_aggregate_t {};
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<Blank> {
|
||||||
|
static std::string get() { return "null"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<Derived> {
|
||||||
|
static std::string get() { return "derived"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<int> {
|
||||||
|
static std::string get() { return "int"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<bool> {
|
||||||
|
static std::string get() { return "bool"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<boost::logic::tribool> {
|
||||||
|
static std::string get() { return "logical"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<double> {
|
||||||
|
static std::string get() { return "real"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<std::string> {
|
||||||
|
static std::string get() { return "string"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<boost::dynamic_bitset<>> {
|
||||||
|
static std::string get() { return "binary"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<EnumerationReference> {
|
||||||
|
static std::string get() { return "enumeration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<IfcUtil::IfcBaseClass*> {
|
||||||
|
static std::string get() { return "instance"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<empty_aggregate_t> {
|
||||||
|
static std::string get() { return "aggregate"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Allocator>
|
||||||
|
struct VariantTypeName<std::vector<T, Allocator>> {
|
||||||
|
static std::string get() { return "aggregate of " + VariantTypeName<T>::get(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<aggregate_of_instance::ptr> {
|
||||||
|
static std::string get() { return "aggregate of instance"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<empty_aggregate_of_aggregate_t> {
|
||||||
|
static std::string get() { return "aggregate of aggregate"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VariantTypeName<aggregate_of_aggregate_of_instance::ptr> {
|
||||||
|
static std::string get() { return "aggregate of aggregate of instance"; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
struct parameter_pack {
|
struct parameter_pack {
|
||||||
static constexpr size_t size = sizeof...(Args);
|
static constexpr size_t size = sizeof...(Args);
|
||||||
|
|||||||
+34
-18
@@ -37,10 +37,28 @@ variant - which is the maximum size of its constituents - is reduced.
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <exception>
|
||||||
#include "IfcException.h"
|
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
class storage_type_mismatch : public std::exception {
|
||||||
|
private:
|
||||||
|
std::string requested_, actual__, message_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
storage_type_mismatch(const std::string& requested, const std::string& actual)
|
||||||
|
: requested_(requested), actual__(actual), message_("Requested type " + requested_ + " does not match actual type " + actual__) {}
|
||||||
|
|
||||||
|
const char* what() const noexcept override {
|
||||||
|
return message_.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& requested() const { return requested_; }
|
||||||
|
const std::string& actual() const { return actual__; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct VariantTypeName;
|
||||||
|
|
||||||
// Trait to detect unique_ptr
|
// Trait to detect unique_ptr
|
||||||
template <typename...> struct is_unique_ptr : std::false_type {};
|
template <typename...> struct is_unique_ptr : std::false_type {};
|
||||||
template<class T, typename... Args>
|
template<class T, typename... Args>
|
||||||
@@ -166,14 +184,13 @@ public:
|
|||||||
using U = std::decay_t<T>;
|
using U = std::decay_t<T>;
|
||||||
static_assert(::impl::TypeIndex_v<U, Types...> < sizeof...(Types), "Type not supported by variant");
|
static_assert(::impl::TypeIndex_v<U, Types...> < sizeof...(Types), "Type not supported by variant");
|
||||||
if (index >= size()) {
|
if (index >= size()) {
|
||||||
throw std::out_of_range("Index out of range");
|
throw std::out_of_range("Index " + std::to_string(index) + " is out of range for storage of size " + std::to_string(size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_at_index(index);
|
destroy_at_index(index);
|
||||||
|
|
||||||
size_and_indices_[index + 1] = ::impl::TypeIndex_v<U, Types...>;
|
size_and_indices_[index + 1] = ::impl::TypeIndex_v<U, Types...>;
|
||||||
using V = typename std::tuple_element<::impl::TypeIndex_v<U, Types...>, ::impl::MapTypes_t<Types... >>::type;
|
using V = typename std::tuple_element<::impl::TypeIndex_v<U, Types...>, ::impl::MapTypes_t<Types... >>::type;
|
||||||
// std::wcout << "setting " << index << " to " << typeid(V).name() << " (" << ::impl::TypeIndex_v<U, Types...> << ")" << std::endl;
|
|
||||||
if constexpr (::impl::is_unique_ptr<V>::value) {
|
if constexpr (::impl::is_unique_ptr<V>::value) {
|
||||||
new(&storage_[index]) V(new U(value));
|
new(&storage_[index]) V(new U(value));
|
||||||
} else {
|
} else {
|
||||||
@@ -187,8 +204,8 @@ public:
|
|||||||
|
|
||||||
std::size_t index(std::size_t index) const {
|
std::size_t index(std::size_t index) const {
|
||||||
if (index >= size()) {
|
if (index >= size()) {
|
||||||
throw IfcParse::IfcException(
|
throw std::out_of_range(
|
||||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
"Index " + std::to_string(index) + " is out of range for storage of size " + std::to_string(size())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return size_and_indices_[index + 1];
|
return size_and_indices_[index + 1];
|
||||||
@@ -197,8 +214,8 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
T& get(std::size_t index) {
|
T& get(std::size_t index) {
|
||||||
if (index >= size()) {
|
if (index >= size()) {
|
||||||
throw IfcParse::IfcException(
|
throw std::out_of_range(
|
||||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
"Index " + std::to_string(index) + " is out of range for storage of size " + std::to_string(size())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!has<T>(index)) {
|
if (!has<T>(index)) {
|
||||||
@@ -220,17 +237,16 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
const T& get(std::size_t index) const {
|
const T& get(std::size_t index) const {
|
||||||
if (index >= size()) {
|
if (index >= size()) {
|
||||||
throw IfcParse::IfcException(
|
throw std::out_of_range(
|
||||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
"Index " + std::to_string(index) + " is out of range for storage of size " + std::to_string(size())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (size_and_indices_[index + 1] != ::impl::TypeIndex<T, Types...>::value) {
|
if (size_and_indices_[index + 1] != ::impl::TypeIndex<T, Types...>::value) {
|
||||||
// @todo this IfcException is silly. Figure out what
|
// @todo this IfcException is silly. Figure out what
|
||||||
// to do, but at the moment it is specifically caught
|
// to do, but at the moment it is specifically caught
|
||||||
// in various places.
|
// in various places.
|
||||||
throw IfcParse::IfcException(
|
throw impl::storage_type_mismatch(
|
||||||
"Type held at index " + std::to_string(index) + " is " +
|
::impl::VariantTypeName<T>::get(), get_type_name(size_and_indices_[index + 1])
|
||||||
get_type_name(size_and_indices_[index + 1]) + " and not " + typeid(T).name()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
using V = typename std::tuple_element<::impl::TypeIndex_v<T, Types...>, ::impl::MapTypes_t<Types... >>::type;
|
using V = typename std::tuple_element<::impl::TypeIndex_v<T, Types...>, ::impl::MapTypes_t<Types... >>::type;
|
||||||
@@ -244,8 +260,8 @@ public:
|
|||||||
template<typename Visitor>
|
template<typename Visitor>
|
||||||
auto apply_visitor(Visitor&& visitor, std::size_t index) const {
|
auto apply_visitor(Visitor&& visitor, std::size_t index) const {
|
||||||
if (index >= size()) {
|
if (index >= size()) {
|
||||||
throw IfcParse::IfcException(
|
throw std::out_of_range(
|
||||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
"Index " + std::to_string(index) + " is out of range for storage of size " + std::to_string(size())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return apply_visitor_impl(std::forward<Visitor>(visitor), index, std::integral_constant<std::size_t, sizeof...(Types)>{});
|
return apply_visitor_impl(std::forward<Visitor>(visitor), index, std::integral_constant<std::size_t, sizeof...(Types)>{});
|
||||||
@@ -312,19 +328,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <size_t I>
|
template <size_t I>
|
||||||
const char* get_type_name_impl(size_t i) const {
|
std::string get_type_name_impl(size_t i) const {
|
||||||
if constexpr (I == 0) {
|
if constexpr (I == 0) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
if (i == I - 1) {
|
if (i == I - 1) {
|
||||||
return typeid(std::tuple_element_t<I - 1, std::tuple<Types...>>).name();
|
return ::impl::VariantTypeName<std::tuple_element_t<I - 1, std::tuple<Types...>>>::get();
|
||||||
} else {
|
} else {
|
||||||
return get_type_name_impl<I - 1>(i);
|
return get_type_name_impl<I - 1>(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* get_type_name(size_t i) const {
|
std::string get_type_name(size_t i) const {
|
||||||
return get_type_name_impl<sizeof...(Types)>(i);
|
return get_type_name_impl<sizeof...(Types)>(i);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user