From f0ee64dae32a5a7e694aa4200dfa69a3bd3d4e49 Mon Sep 17 00:00:00 2001 From: Martin Henselmeyer Date: Fri, 15 Dec 2023 09:40:54 +0100 Subject: [PATCH] fable: Fix excessive compilation duration BREAKING CHANGES: - Removed all make_schema() functions that do not fall into one of the two signatures: make_schema(T*, std::string&&) make_schema(T*, P&&, std::string&&) So far, only the two forms above have been used, and the others aren't strictly required and don't contribute to readability. --- fable/include/fable/make_schema.hpp | 103 ++++++++++++++++++++++++ fable/include/fable/schema.hpp | 25 +----- fable/include/fable/schema/array.hpp | 14 ++-- fable/include/fable/schema/boolean.hpp | 2 +- fable/include/fable/schema/confable.hpp | 2 +- fable/include/fable/schema/const.hpp | 10 +-- fable/include/fable/schema/duration.hpp | 2 +- fable/include/fable/schema/enum.hpp | 2 +- fable/include/fable/schema/ignore.hpp | 4 - fable/include/fable/schema/json.hpp | 5 -- fable/include/fable/schema/magic.hpp | 12 +-- fable/include/fable/schema/map.hpp | 14 ++-- fable/include/fable/schema/number.hpp | 2 +- fable/include/fable/schema/optional.hpp | 10 +-- fable/include/fable/schema/passthru.hpp | 12 +-- fable/include/fable/schema/path.hpp | 2 +- fable/include/fable/schema/string.hpp | 2 +- fable/include/fable/schema/struct.hpp | 20 ----- fable/include/fable/schema/variant.hpp | 10 --- 19 files changed, 148 insertions(+), 105 deletions(-) create mode 100644 fable/include/fable/make_schema.hpp diff --git a/fable/include/fable/make_schema.hpp b/fable/include/fable/make_schema.hpp new file mode 100644 index 000000000..46a8ec486 --- /dev/null +++ b/fable/include/fable/make_schema.hpp @@ -0,0 +1,103 @@ +/* + * Copyright 2023 Robert Bosch GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * \file fable/make_schema.hpp + * + * This file provides a facade for the make_schema function which implements + * a short-cut for the compiler which reduces the excessive resource + * consumption of the actual implementation. + */ + +#pragma once + +#include // for string + +#include // for Array<> +#include // for Boolean +#include // for FromConfable +#include // for Const<> +#include // for Duration<> +#include // for Enum<> +#include // for Ignore +#include // for Interface, Box +#include // for FromJson<> +#include // for Map<> +#include // for Number<> +#include // for Optional<> +#include // for Passthru +#include // for Path +#include // for String +#include // for Struct +#include // for Variant + +// It is important that this include comes after all the other ones, +// so that it has access to ALL the previous definitions. +#include // for make_prototype, ... + +namespace fable::schema { +namespace details { + +/** + * Implements the make_schema function for one datatype + */ +template +struct make_schema_wrapper1 { + static auto make_schema(T* ptr, std::string&& desc) { + return ::fable::schema::make_schema_impl(ptr, std::move(desc)); + } +}; + +/** + */ +template +struct make_schema_wrapper2 { + static auto make_schema(T* ptr, P proto, std::string&& desc) { + return ::fable::schema::make_schema_impl(ptr, std::move(proto), std::move(desc)); + } +}; + +} // namespace details + +/** + * Returns the schema for a given datum and its description + * + * \param ptr Pointer to the datum + * \param desc Textual description of the datum + * \return Schema for the datum + */ +template +auto make_schema(T* ptr, std::string&& desc) { + return details::make_schema_wrapper1::make_schema(ptr, std::move(desc)); +} + +/** + * Returns the schema for a given datum and its description + * + * \param ptr Pointer to the datum + * \param proto Prototype of the data-value + * \param desc Textual description of the datum + * \return Schema for the datum + * \note Those types which have a prototype, namely string & path + * do not matter for the compile-time reduction + */ +template +auto make_schema(T* ptr, P proto, std::string&& desc) { + return details::make_schema_wrapper2::make_schema(ptr, std::move(proto), std::move(desc)); +} + +} // namespace fable::schema diff --git a/fable/include/fable/schema.hpp b/fable/include/fable/schema.hpp index 86cab04ca..49c6b680d 100644 --- a/fable/include/fable/schema.hpp +++ b/fable/include/fable/schema.hpp @@ -122,29 +122,7 @@ #include // for move #include // for vector<> -#include // for optional<> - -#include // for Array<> -#include // for Boolean -#include // for FromConfable -#include // for Const<> -#include // for Duration<> -#include // for Enum<> -#include // for Ignore -#include // for Interface, Box -#include // for FromJson<> -#include // for Map<> -#include // for Number<> -#include // for Optional<> -#include // for Passthru -#include // for Path -#include // for String -#include // for Struct -#include // for Variant - -// It is important that this include comes after all the other ones, -// so that it has access to ALL the previous definitions. -#include // for make_prototype, ... +#include // for make_schema namespace fable { @@ -153,6 +131,7 @@ using schema::make_const_schema; using schema::make_const_str; using schema::make_prototype; using schema::make_schema; +using schema::make_schema_impl; /** * Define the automatically deduced schema class of a given type. diff --git a/fable/include/fable/schema/array.hpp b/fable/include/fable/schema/array.hpp index cfb7ed800..370686f09 100644 --- a/fable/include/fable/schema/array.hpp +++ b/fable/include/fable/schema/array.hpp @@ -40,13 +40,13 @@ template class Array : public Base> { public: // Types and Constructors using Type = std::vector; - using PrototypeSchema = P; + using PrototypeSchema = std::remove_cv_t>; Array(Type* ptr, std::string&& desc); - Array(Type* ptr, const PrototypeSchema& prototype) - : Base>(JsonType::array), prototype_(prototype), ptr_(ptr) {} - Array(Type* ptr, const PrototypeSchema& prototype, std::string&& desc) - : Base>(JsonType::array, std::move(desc)), prototype_(prototype), ptr_(ptr) {} + Array(Type* ptr, PrototypeSchema prototype) + : Base>(JsonType::array), prototype_(std::move(prototype)), ptr_(ptr) {} + Array(Type* ptr, PrototypeSchema prototype, std::string&& desc) + : Base>(JsonType::array, std::move(desc)), prototype_(std::move(prototype)), ptr_(ptr) {} #if 0 // This is defined in: fable/schema/magic.hpp @@ -174,8 +174,8 @@ class Array : public Base> { }; template -Array make_schema(std::vector* ptr, const P& prototype, std::string&& desc) { - return Array(ptr, prototype, std::move(desc)); +Array make_schema_impl(std::vector* ptr, P&& prototype, std::string&& desc) { + return Array(ptr, std::forward

(prototype), std::move(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/boolean.hpp b/fable/include/fable/schema/boolean.hpp index ed3d695a3..1756d7f62 100644 --- a/fable/include/fable/schema/boolean.hpp +++ b/fable/include/fable/schema/boolean.hpp @@ -51,7 +51,7 @@ class Boolean : public Base { Type* ptr_{nullptr}; }; -inline Boolean make_schema(bool* ptr, std::string&& desc) { return Boolean(ptr, std::move(desc)); } +inline Boolean make_schema_impl(bool* ptr, std::string&& desc) { return Boolean(ptr, std::move(desc)); } } // namespace schema } // namespace fable diff --git a/fable/include/fable/schema/confable.hpp b/fable/include/fable/schema/confable.hpp index 06bd0e835..1bf846d52 100644 --- a/fable/include/fable/schema/confable.hpp +++ b/fable/include/fable/schema/confable.hpp @@ -104,7 +104,7 @@ class FromConfable : public Base> { }; template -FromConfable make_schema(T* ptr, std::string&& desc) { +FromConfable make_schema_impl(T* ptr, std::string&& desc) { assert(ptr != nullptr); return FromConfable(ptr, std::move(desc)); } diff --git a/fable/include/fable/schema/const.hpp b/fable/include/fable/schema/const.hpp index d4abdaf8b..666e0dcd7 100644 --- a/fable/include/fable/schema/const.hpp +++ b/fable/include/fable/schema/const.hpp @@ -37,12 +37,12 @@ template class Const : public Base> { public: // Types and Constructors using Type = T; - using PrototypeSchema = P; + using PrototypeSchema = std::remove_cv_t>; Const(const Type& constant, std::string&& desc); - Const(const Type& constant, const PrototypeSchema& prototype, std::string&& desc) + Const(const Type& constant, PrototypeSchema prototype, std::string&& desc) : Base>(prototype.type(), std::move(desc)) - , prototype_(prototype) + , prototype_(std::move(prototype)) , constant_(constant) { prototype_.reset_ptr(); } @@ -89,8 +89,8 @@ class Const : public Base> { }; template -Const make_const_schema(const T& constant, const P& prototype, std::string&& desc) { - return Const(constant, prototype, std::move(desc)); +Const make_const_schema(const T& constant, P&& prototype, std::string&& desc) { + return Const(constant, std::forward

(prototype), std::move(desc)); } inline Const make_const_str(const std::string& constant, std::string&& desc) { diff --git a/fable/include/fable/schema/duration.hpp b/fable/include/fable/schema/duration.hpp index edaf6cb66..a7acc0c6a 100644 --- a/fable/include/fable/schema/duration.hpp +++ b/fable/include/fable/schema/duration.hpp @@ -187,7 +187,7 @@ class Duration : public Base> { }; template -inline Duration make_schema(std::chrono::duration* ptr, +inline Duration make_schema_impl(std::chrono::duration* ptr, std::string&& desc) { return Duration(ptr, std::move(desc)); } diff --git a/fable/include/fable/schema/enum.hpp b/fable/include/fable/schema/enum.hpp index 91a7c1158..6eb11ea7c 100644 --- a/fable/include/fable/schema/enum.hpp +++ b/fable/include/fable/schema/enum.hpp @@ -103,7 +103,7 @@ class Enum : public Base> { }; template ::value, int> = 0> -inline Enum make_schema(T* ptr, std::string&& desc) { +inline Enum make_schema_impl(T* ptr, std::string&& desc) { return Enum(ptr, std::move(desc)); } diff --git a/fable/include/fable/schema/ignore.hpp b/fable/include/fable/schema/ignore.hpp index 4973345ca..b62c1c48b 100644 --- a/fable/include/fable/schema/ignore.hpp +++ b/fable/include/fable/schema/ignore.hpp @@ -60,9 +60,5 @@ class Ignore : public Base { void reset_ptr() override {} }; -inline Ignore make_schema(std::string&& desc, JsonType t = JsonType::object) { - return Ignore(std::move(desc), t); -} - } // namespace schema } // namespace fable diff --git a/fable/include/fable/schema/json.hpp b/fable/include/fable/schema/json.hpp index 09ae6cfd3..883f9fb5d 100644 --- a/fable/include/fable/schema/json.hpp +++ b/fable/include/fable/schema/json.hpp @@ -79,10 +79,5 @@ class FromJson : public Base> { Type* ptr_{nullptr}; }; -template -inline FromJson make_schema(T* ptr, JsonType t, std::string&& desc) { - return FromJson(ptr, t, std::move(desc)); -} - } // namespace schema } // namespace fable diff --git a/fable/include/fable/schema/magic.hpp b/fable/include/fable/schema/magic.hpp index 4e69e1b77..a5ef24fe3 100644 --- a/fable/include/fable/schema/magic.hpp +++ b/fable/include/fable/schema/magic.hpp @@ -21,10 +21,10 @@ * \see fable/schema_test.cpp * * This file defines the `make_prototype` functions that can automatically - * derive the prototype via the `make_schema` functions. It also contains the + * derive the prototype via the `make_schema_impl` functions. It also contains the * definitions of constructors that make use of these functions. * - * Unfortunately, all `make_schema` functions need to already be defined at the + * Unfortunately, all `make_schema_impl` functions need to already be defined at the * point of definition of these constructors, which is why they have to be in * this file in the first place. * @@ -58,7 +58,7 @@ Array::Array(std::vector* ptr, std::string&& desc) : Array(ptr, make_prototype(), std::move(desc)) {} template -Array())> make_schema(std::vector* ptr, std::string&& desc) { +Array())> make_schema_impl(std::vector* ptr, std::string&& desc) { return Array())>(ptr, std::move(desc)); } @@ -76,7 +76,7 @@ Map::Map(std::map* ptr, std::string&& desc) : Map(ptr, make_prototype(), std::move(desc)) {} template -Map())> make_schema(std::map* ptr, +Map())> make_schema_impl(std::map* ptr, std::string&& desc) { return Map())>(ptr, std::move(desc)); } @@ -86,7 +86,7 @@ Optional::Optional(boost::optional* ptr, std::string&& desc) : Optional(ptr, make_prototype(), std::move(desc)) {} template -Optional())> make_schema(boost::optional* ptr, +Optional())> make_schema_impl(boost::optional* ptr, std::string&& desc) { return Optional())>(ptr, std::move(desc)); } @@ -98,7 +98,7 @@ auto make_prototype(std::string&& desc) { template ::value, int>> auto make_prototype(std::string&& desc) { - return make_schema(static_cast(nullptr), std::move(desc)); + return make_schema_impl(static_cast(nullptr), std::move(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/map.hpp b/fable/include/fable/schema/map.hpp index 3d52a3418..127722560 100644 --- a/fable/include/fable/schema/map.hpp +++ b/fable/include/fable/schema/map.hpp @@ -50,15 +50,15 @@ template class Map : public Base> { public: // Types and Constructors using Type = std::map; - using PrototypeSchema = P; + using PrototypeSchema = std::remove_cv_t>; Map(Type* ptr, std::string&& desc); - Map(Type* ptr, const PrototypeSchema& prototype) - : Base>(JsonType::object), prototype_(prototype), ptr_(ptr) { + Map(Type* ptr, PrototypeSchema prototype) + : Base>(JsonType::object), prototype_(std::move(prototype)), ptr_(ptr) { prototype_.reset_ptr(); } - Map(Type* ptr, const PrototypeSchema& prototype, std::string&& desc) - : Base>(JsonType::object, std::move(desc)), prototype_(prototype), ptr_(ptr) { + Map(Type* ptr, PrototypeSchema prototype, std::string&& desc) + : Base>(JsonType::object, std::move(desc)), prototype_(std::move(prototype)), ptr_(ptr) { prototype_.reset_ptr(); } @@ -189,8 +189,8 @@ class Map : public Base> { }; template -Map make_schema(std::map* ptr, const P& prototype, std::string&& desc) { - return Map(ptr, prototype, std::move(desc)); +Map make_schema_impl(std::map* ptr, P&& prototype, std::string&& desc) { + return Map(ptr, std::forward

(prototype), std::move(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/number.hpp b/fable/include/fable/schema/number.hpp index 305ed5492..068a50bce 100644 --- a/fable/include/fable/schema/number.hpp +++ b/fable/include/fable/schema/number.hpp @@ -104,7 +104,7 @@ class Number : public Base> { template ::value && !std::is_enum::value, int> = 0> -inline Number make_schema(T* ptr, std::string&& desc) { +inline Number make_schema_impl(T* ptr, std::string&& desc) { return Number(ptr, std::move(desc)); } diff --git a/fable/include/fable/schema/optional.hpp b/fable/include/fable/schema/optional.hpp index ae67180db..fa111e4b4 100644 --- a/fable/include/fable/schema/optional.hpp +++ b/fable/include/fable/schema/optional.hpp @@ -39,11 +39,11 @@ template class Optional : public Base> { public: // Types and Constructors using Type = boost::optional; - using PrototypeSchema = P; + using PrototypeSchema = std::remove_cv_t>; Optional(Type* ptr, std::string&& desc); - Optional(Type* ptr, const PrototypeSchema& prototype, std::string&& desc) - : Base>(prototype.type(), std::move(desc)), prototype_(prototype), ptr_(ptr) { + Optional(Type* ptr, PrototypeSchema prototype, std::string&& desc) + : Base>(prototype.type(), std::move(desc)), prototype_(std::move(prototype)), ptr_(ptr) { prototype_.reset_ptr(); } @@ -113,8 +113,8 @@ class Optional : public Base> { }; template -Optional make_schema(boost::optional* ptr, const P& prototype, std::string&& desc) { - return Optional(ptr, prototype, std::move(desc)); +Optional make_schema_impl(boost::optional* ptr, P&& prototype, std::string&& desc) { + return Optional(ptr, std::forward

(prototype), std::move(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/passthru.hpp b/fable/include/fable/schema/passthru.hpp index 78ef45244..d514b8066 100644 --- a/fable/include/fable/schema/passthru.hpp +++ b/fable/include/fable/schema/passthru.hpp @@ -46,12 +46,12 @@ template class Passthru : public Base> { public: // Types and Constructors using Type = Conf; - using PrototypeSchema = P; + using PrototypeSchema = std::remove_cv_t>; Passthru(Type* ptr, std::string&& desc) : Passthru(ptr, PrototypeSchema(nullptr, ""), std::move(desc)) {} - Passthru(Type* ptr, const PrototypeSchema& prototype, std::string&& desc) - : Base>(prototype.type(), std::move(desc)), prototype_(prototype), ptr_(ptr) { + Passthru(Type* ptr, PrototypeSchema prototype, std::string&& desc) + : Base>(prototype.type(), std::move(desc)), prototype_(std::move(prototype)), ptr_(ptr) { prototype_.reset_ptr(); } @@ -92,13 +92,13 @@ class Passthru : public Base> { Type* ptr_{nullptr}; }; -inline Passthru make_schema(Conf* ptr, std::string&& desc) { +inline Passthru make_schema_impl(Conf* ptr, std::string&& desc) { return Passthru(ptr, Ignore(), std::move(desc)); } template -Passthru

make_schema(Conf* ptr, const P& prototype, std::string&& desc) { - return Passthru

(ptr, prototype, std::move(desc)); +Passthru

make_schema_impl(Conf* ptr, P&& prototype, std::string&& desc) { + return Passthru

(ptr, std::forward

(prototype), std::move(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/path.hpp b/fable/include/fable/schema/path.hpp index b17536747..abbbcf76a 100644 --- a/fable/include/fable/schema/path.hpp +++ b/fable/include/fable/schema/path.hpp @@ -213,7 +213,7 @@ class Path : public Base { Type* ptr_{nullptr}; }; -inline Path make_schema(boost::filesystem::path* ptr, std::string&& desc) { +inline Path make_schema_impl(boost::filesystem::path* ptr, std::string&& desc) { return Path(ptr, std::move(desc)); } diff --git a/fable/include/fable/schema/string.hpp b/fable/include/fable/schema/string.hpp index 5d3ba12a0..54bea643e 100644 --- a/fable/include/fable/schema/string.hpp +++ b/fable/include/fable/schema/string.hpp @@ -261,7 +261,7 @@ class String : public Base { Type* ptr_{nullptr}; }; -inline String make_schema(std::string* ptr, std::string&& desc) { +inline String make_schema_impl(std::string* ptr, std::string&& desc) { return String(ptr, std::move(desc)); } diff --git a/fable/include/fable/schema/struct.hpp b/fable/include/fable/schema/struct.hpp index efa95ac2e..dae7f046a 100644 --- a/fable/include/fable/schema/struct.hpp +++ b/fable/include/fable/schema/struct.hpp @@ -217,25 +217,5 @@ class Struct : public Base { bool additional_properties_{false}; }; -template > -inline Struct make_schema(T&& props) { - return Struct(std::forward(props)); -} - -template > -inline Struct make_schema(std::string&& desc, T&& props) { - return Struct(std::move(desc), std::forward(props)); -} - -template > -inline Struct make_schema(std::string&& desc, const Box& base, T&& props) { - return Struct(std::move(desc), base, std::forward(props)); -} - -template > -inline Struct make_schema(std::string&& desc, const Struct& base, T&& props) { - return Struct(std::move(desc), base, std::forward(props)); -} - } // namespace schema } // namespace fable diff --git a/fable/include/fable/schema/variant.hpp b/fable/include/fable/schema/variant.hpp index f424102ae..05176f9a1 100644 --- a/fable/include/fable/schema/variant.hpp +++ b/fable/include/fable/schema/variant.hpp @@ -125,15 +125,5 @@ class Variant : public Interface { bool unique_match_{false}; }; -inline Variant make_schema(std::initializer_list vec) { return Variant(vec); } -inline Variant make_schema(std::string&& desc, std::initializer_list vec) { - return Variant(std::move(desc), std::vector(vec)); -} - -inline Variant make_schema(std::vector&& vec) { return Variant(std::move(vec)); } -inline Variant make_schema(std::string&& desc, std::vector&& vec) { - return Variant(std::move(desc), std::move(vec)); -} - } // namespace schema } // namespace fable