mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-05 23:41:44 +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_)
|
||||
{
|
||||
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
|
||||
else {
|
||||
|
||||
@@ -72,6 +72,83 @@ class IFC_PARSE_API Derived {};
|
||||
class IFC_PARSE_API empty_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>
|
||||
struct parameter_pack {
|
||||
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 <cstddef>
|
||||
#include <limits>
|
||||
|
||||
#include "IfcException.h"
|
||||
#include <exception>
|
||||
|
||||
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
|
||||
template <typename...> struct is_unique_ptr : std::false_type {};
|
||||
template<class T, typename... Args>
|
||||
@@ -166,14 +184,13 @@ public:
|
||||
using U = std::decay_t<T>;
|
||||
static_assert(::impl::TypeIndex_v<U, Types...> < sizeof...(Types), "Type not supported by variant");
|
||||
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);
|
||||
|
||||
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;
|
||||
// std::wcout << "setting " << index << " to " << typeid(V).name() << " (" << ::impl::TypeIndex_v<U, Types...> << ")" << std::endl;
|
||||
if constexpr (::impl::is_unique_ptr<V>::value) {
|
||||
new(&storage_[index]) V(new U(value));
|
||||
} else {
|
||||
@@ -187,8 +204,8 @@ public:
|
||||
|
||||
std::size_t index(std::size_t index) const {
|
||||
if (index >= size()) {
|
||||
throw IfcParse::IfcException(
|
||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
||||
throw std::out_of_range(
|
||||
"Index " + std::to_string(index) + " is out of range for storage of size " + std::to_string(size())
|
||||
);
|
||||
}
|
||||
return size_and_indices_[index + 1];
|
||||
@@ -197,8 +214,8 @@ public:
|
||||
template<typename T>
|
||||
T& get(std::size_t index) {
|
||||
if (index >= size()) {
|
||||
throw IfcParse::IfcException(
|
||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
||||
throw std::out_of_range(
|
||||
"Index " + std::to_string(index) + " is out of range for storage of size " + std::to_string(size())
|
||||
);
|
||||
}
|
||||
if (!has<T>(index)) {
|
||||
@@ -220,17 +237,16 @@ public:
|
||||
template<typename T>
|
||||
const T& get(std::size_t index) const {
|
||||
if (index >= size()) {
|
||||
throw IfcParse::IfcException(
|
||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
||||
throw std::out_of_range(
|
||||
"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) {
|
||||
// @todo this IfcException is silly. Figure out what
|
||||
// to do, but at the moment it is specifically caught
|
||||
// in various places.
|
||||
throw IfcParse::IfcException(
|
||||
"Type held at index " + std::to_string(index) + " is " +
|
||||
get_type_name(size_and_indices_[index + 1]) + " and not " + typeid(T).name()
|
||||
throw impl::storage_type_mismatch(
|
||||
::impl::VariantTypeName<T>::get(), get_type_name(size_and_indices_[index + 1])
|
||||
);
|
||||
}
|
||||
using V = typename std::tuple_element<::impl::TypeIndex_v<T, Types...>, ::impl::MapTypes_t<Types... >>::type;
|
||||
@@ -244,8 +260,8 @@ public:
|
||||
template<typename Visitor>
|
||||
auto apply_visitor(Visitor&& visitor, std::size_t index) const {
|
||||
if (index >= size()) {
|
||||
throw IfcParse::IfcException(
|
||||
"Index " + std::to_string(index) + " is out of range for variant of size " + std::to_string(size())
|
||||
throw std::out_of_range(
|
||||
"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)>{});
|
||||
@@ -312,19 +328,19 @@ private:
|
||||
}
|
||||
|
||||
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) {
|
||||
return "";
|
||||
} else {
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user