From 95a094d596f337773babc8d0c309e600565c6db2 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 26 Mar 2026 10:39:29 +0100 Subject: [PATCH] Fix some schema generation issues --- .../ifcopenshell/express/implementation.py | 2 +- .../ifcopenshell/express/templates.py | 4 +- src/ifcparse/express.h | 65 ++++++++++++------- src/ifcwrap/IfcPython.i | 18 ----- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/express/implementation.py b/src/ifcopenshell-python/ifcopenshell/express/implementation.py index 478922b42d..37c89dff79 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/implementation.py +++ b/src/ifcopenshell-python/ifcopenshell/express/implementation.py @@ -371,7 +371,7 @@ class Implementation(codegen.Base): # ("const std::weak_ptr& e",), # "", # ), - ("", "", initializer, "", ("%s v" % type_str,), ("set_attribute_value(0, %s(v));" % ("cast_vector" if mapping.is_templated_list(type) else ""))) if mapping.simple_type_parent(class_name) is None else \ + ("", "", initializer, "", ("%s v" % type_str,), ("set_attribute_value(0, %s(v));" % ("cast_vector" if mapping.is_templated_list(type) else ""))), # ("v", "", constructor, "", ("%s v" % type_str,), ""), ("", "", templates.cast_function, type_str, (), simpletype_impl_cast), ), diff --git a/src/ifcopenshell-python/ifcopenshell/express/templates.py b/src/ifcopenshell-python/ifcopenshell/express/templates.py index 3fe73bd9b4..05aa541e5f 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/templates.py +++ b/src/ifcopenshell-python/ifcopenshell/express/templates.py @@ -264,7 +264,7 @@ get_attr_stmt = "%(null_check)s %(non_optional_type)s v = get_attribute_value(%( get_attr_stmt_enum = "%(null_check)s return %(non_optional_type)s::FromString(get_attribute_value(%(index)d));" get_attr_stmt_entity = "%(null_check)s return ((express::Base)(get_attribute_value(%(index)d))).as<%(non_optional_type_no_pointer)s>();" get_attr_stmt_array = "%(null_check)s std::vector es = get_attribute_value(%(index)d); return cast_vector<%(list_instance_type)s>(es);" -get_attr_stmt_nested_array = "%(null_check)s std::vector> es = get_attribute_value(%(index)d); return cast_vector_vector<%(list_instance_type)s>(es);" +get_attr_stmt_nested_array = "%(null_check)s std::vector> es = get_attribute_value(%(index)d); return cast_vector<%(list_instance_type)s>(es);" get_inverse = "return cast_vector<%(type)s>(file()->getInverse(data()->id(), %(schema_name_upper)s_types[%(type_index)d], %(index)d));" @@ -279,7 +279,7 @@ set_attr_stmt_array = ( "%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" ) set_attr_stmt_nested_array = ( - "%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector_vector(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" + "%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" ) constructor_stmt = ( diff --git a/src/ifcparse/express.h b/src/ifcparse/express.h index ef16641d11..293cc30e2f 100644 --- a/src/ifcparse/express.h +++ b/src/ifcparse/express.h @@ -205,32 +205,53 @@ struct hash { } // namespace boost -template -std::vector cast_vector(const std::vector& vs) { - std::vector result; - for (const auto& v : vs) { - if constexpr (std::is_base_of_v) { - // For a base or identity transform we can just rely on static cast - result.push_back(v); - } else if constexpr (std::is_base_of_v && std::is_same_v) { - // From a select to concrete we simply call the appropriate method - result.push_back(v.concrete()); - } else { - if (auto u = v.template as()) { - result.push_back(u); - } - } - } - return result; +namespace { +template +struct is_std_vector : std::false_type {}; + +template +struct is_std_vector> : std::true_type {}; + +template +constexpr bool is_std_vector_v = is_std_vector::value; + +template +struct is_std_vector_vector : std::false_type {}; + +template +struct is_std_vector_vector, Alloc2>> : std::true_type {}; + +template +constexpr bool is_std_vector_vector_v = is_std_vector_vector::value; } template -std::vector> cast_vector_vector(const std::vector>& vs) { - std::vector> result; - for (const auto& v : vs) { - result.push_back(cast_vector(v)); +auto cast_vector(const std::vector& vs) { + if constexpr (is_std_vector::value) { + using V = typename U::value_type; + std::vector> result; + result.reserve(vs.size()); + for (const auto& v : vs) { + result.push_back(cast_vector(v)); + } + return result; + } else { + std::vector result; + for (const auto& v : vs) { + if constexpr (std::is_base_of_v) { + // For a base or identity transform we can just rely on static cast + result.push_back(v); + } else if constexpr (std::is_base_of_v && std::is_same_v) { + // From a select to concrete we simply call the appropriate method + result.push_back(v.concrete()); + } else { + if (auto u = v.template as()) { + result.push_back(u); + } + } + } + return result; } - return result; } #endif diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i index c96036ea4f..4e9cacf75d 100644 --- a/src/ifcwrap/IfcPython.i +++ b/src/ifcwrap/IfcPython.i @@ -262,24 +262,6 @@ #endif %} -%{ - -template -struct is_std_vector : std::false_type {}; -template -struct is_std_vector> : std::true_type {}; -template -constexpr bool is_std_vector_v = is_std_vector::value; - -template -struct is_std_vector_vector : std::false_type {}; -template -struct is_std_vector_vector, Alloc2>> : std::true_type {}; -template -constexpr bool is_std_vector_vector_v = is_std_vector_vector::value; - -%} - // Create docstrings for generated python code. %feature("autodoc", "1");