diff --git a/fable/examples/stress/CMakeLists.txt b/fable/examples/stress/CMakeLists.txt new file mode 100644 index 000000000..0233ff7db --- /dev/null +++ b/fable/examples/stress/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +project(fable_stress_test LANGUAGES CXX) + +set(LARGE_STRUCT_SIZE 1000 CACHE NUMBER "Number of members of Large struct") + +find_package(CLI11 REQUIRED) +find_package(fable REQUIRED) +find_package(fmt REQUIRED) + +# Executable --------------------------------------------------------- +add_custom_command( + OUTPUT large_struct.hxx + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/gen.py ${LARGE_STRUCT_SIZE} ${CMAKE_CURRENT_BINARY_DIR}/large_struct.hxx + VERBATIM +) +add_executable(stress + src/main.cpp + large_struct.hxx +) +target_include_directories(stress + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} +) +set_target_properties(stress PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON +) +target_link_libraries(stress + PRIVATE + fable::fable + fmt::fmt + CLI11::CLI11 +) diff --git a/fable/examples/stress/Makefile b/fable/examples/stress/Makefile new file mode 100644 index 000000000..24d3172d0 --- /dev/null +++ b/fable/examples/stress/Makefile @@ -0,0 +1,31 @@ +# This is a minimal Makefile to show how this example project +# can be built with Conan and CMake. + +# All generated and compiled output is in this directory. +BUILD_DIR := build + +# The build type must be synchronized between Conan (host build type) +# and CMake, otherwise you will get strange and unhelpful errors. +BUILD_TYPE := Release +CMAKE_BUILD_TYPE := $(shell echo ${BUILD_TYPE} | tr '[:upper:]' '[:lower:]') + +# This is the output that Conan generates when using +# `CMakeToolchain` generator AND the `cmake_layout` layout. +TOOLCHAIN_FILE := ${BUILD_DIR}/${BUILD_TYPE}/generators/conan_toolchain.cmake + +# How many variables should the "Large" struct have? +LARGE_STRUCT_SIZE := 1000 + +FABLE_VERSION := $(shell make --quiet -C ../.. info-fqn) + +.PHONY: all clean +all: ${TOOLCHAIN_FILE} + cmake --build --preset=${CMAKE_BUILD_TYPE} + +${TOOLCHAIN_FILE}: + conan install . --build=missing --install-folder=${BUILD_DIR} -s:h build_type=${BUILD_TYPE} --require-override ${FABLE_VERSION} + cmake --preset=${CMAKE_BUILD_TYPE} -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLARGE_STRUCT_SIZE=${LARGE_STRUCT_SIZE} + +clean: + -rm -r ${BUILD_DIR} + -rm CMakeUserPresets.json diff --git a/fable/examples/stress/README.md b/fable/examples/stress/README.md new file mode 100644 index 000000000..264d66e7c --- /dev/null +++ b/fable/examples/stress/README.md @@ -0,0 +1,2 @@ +This example project stresses the compiler by forcing it to compile +an extremely large struct. diff --git a/fable/examples/stress/conanfile.txt b/fable/examples/stress/conanfile.txt new file mode 100644 index 000000000..6a9e895a6 --- /dev/null +++ b/fable/examples/stress/conanfile.txt @@ -0,0 +1,15 @@ +# This is a minimal conanfile.txt to show how this example project +# can be built with Conan and CMake. + +[requires] +cli11/2.3.2 +fable/[>=0.20.0, include_prerelease=True]@cloe/develop +fmt/9.1.0 +boost/[>=1.65.1] + +[generators] +CMakeDeps +CMakeToolchain + +[layout] +cmake_layout diff --git a/fable/examples/stress/gen.py b/fable/examples/stress/gen.py new file mode 100755 index 000000000..5b9755762 --- /dev/null +++ b/fable/examples/stress/gen.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +import random +import string +import argparse + +SIMPLE_TYPES = [ + "bool", + "uint8_t", + "uint16_t", + "uint32_t", + "uint64_t", + "int8_t", + "int16_t", + "int32_t", + "int64_t", + "std::string", +] + +COMPLEX_TYPES = [ + "std::vector", + "std::map", + "boost::optional", + # "std::array", # not supported yet +] + +ALL_TYPES = SIMPLE_TYPES + COMPLEX_TYPES + +def generate_random_type(): + def _tvector(): + inner = random.choice(SIMPLE_TYPES) + return f"std::vector<{inner}>" + + def _tmap(): + inner = random.choice(SIMPLE_TYPES) + return f"std::map" + + def _toptional(): + inner = random.choice(SIMPLE_TYPES) + return f"boost::optional<{inner}>" + + def _tarray(): + inner = random.choice(SIMPLE_TYPES) + length = random.randint(2, 24) + return f"std::array<{inner}, {length}>" + + mapper = { + "std::vector": _tvector, + "std::map": _tmap, + "boost::optional": _toptional, + } + + result = random.choice(ALL_TYPES) + if result in COMPLEX_TYPES: + return mapper[result]() + return result + +def generate_random_word(): + letters = string.ascii_letters + return ''.join(random.choice(letters) for _ in range(20)) + +TEMPLATE = string.Template(""" +#pragma once + +struct Large : public fable::Confable { + $variable_lines + + CONFABLE_SCHEMA(Large) { + using namespace fable; + return Schema{ + $schema_lines + }; + } +}; +""") + +def generate(count) -> str: + variable_lines = [] + schema_lines = [] + for i in range(count): + random_word = generate_random_word() + variable_lines.append(f"{generate_random_type()} v{i};") + schema_lines.append('{{"{0}", make_schema(&v{1}, "")}},'.format(random_word, i)) + result = TEMPLATE.substitute({ + "variable_lines": "\n ".join(variable_lines), + "schema_lines": "\n ".join(schema_lines), + }) + return result + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("count", default=10, type=int) + parser.add_argument("output", default="-", type=str) + args = parser.parse_args() + + result = generate(args.count) + if args.output == "-": + print(result) + else: + with open(args.output, "w") as file: + file.write(result) + +if __name__ == "__main__": + main() diff --git a/fable/examples/stress/src/main.cpp b/fable/examples/stress/src/main.cpp new file mode 100644 index 000000000..8c13895f9 --- /dev/null +++ b/fable/examples/stress/src/main.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 2021 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/examples/stress/src/main.cpp + * + * In this example application, we will stress-test the compilation. + * We will be re-using types from the contacts example. + */ + +#include // for std::{cout, cerr} +#include // for std::string<> +#include // for std::vector<> + +#include // for fmt::format +#include // for CLI::App +#include // for boost::optional<> + +#include // for fable::{Confable, CONFABLE_SCHEMA} +#include // for fable::{Schema, String} +#include // for fable::{read_conf} + +#include "large_struct.hxx" + +int main(int argc, char** argv) { + // Parse command line arguments: + CLI::App app("Fable Stress Test Example"); + std::string filename; + CLI11_PARSE(app, argc, argv); + + Large large; + std::cout << large.schema().to_json().dump(2) << std::endl; +} diff --git a/fable/include/fable/enum.hpp b/fable/include/fable/enum.hpp index 60d55ff60..31a77c0d2 100644 --- a/fable/include/fable/enum.hpp +++ b/fable/include/fable/enum.hpp @@ -149,22 +149,22 @@ struct EnumSerializerImpl { } }; -template ::value, int> = 0> +template , int> = 0> const std::map& enum_serialization() { return EnumSerializerImpl::value>::serialization_impl(); } -template ::value, int> = 0> +template , int> = 0> const std::map& enum_deserialization() { return EnumSerializerImpl::value>::deserialization_impl(); } -template ::value, int> = 0> +template , int> = 0> std::string to_string(T x) { return enum_serialization().at(x); } -template ::value, int> = 0> +template , int> = 0> T from_string(const std::string& s) { return enum_deserialization().at(s); } diff --git a/fable/include/fable/schema.hpp b/fable/include/fable/schema.hpp index 86cab04ca..6a5005c64 100644 --- a/fable/include/fable/schema.hpp +++ b/fable/include/fable/schema.hpp @@ -114,16 +114,12 @@ #pragma once -#include // for duration<> -#include // for map<> #include // for shared_ptr<> #include // for string #include // for enable_if_t<>, is_arithmetic<>, is_enum<>, ... #include // for move #include // for vector<> -#include // for optional<> - #include // for Array<> #include // for Boolean #include // for FromConfable @@ -181,28 +177,28 @@ class Schema : public schema::Interface { Schema& operator=(const Schema&) = default; // Struct - Schema(std::string&& desc, schema::PropertyList<> props) + Schema(std::string desc, schema::PropertyList<> props) : impl_(new schema::Struct(std::move(desc), props)) {} Schema(schema::PropertyList<> props) : Schema("", props) {} - Schema(std::string&& desc, const Schema& base, schema::PropertyList<> props) + Schema(std::string desc, const Schema& base, schema::PropertyList<> props) : impl_(new schema::Struct(std::move(desc), base, props)) {} Schema(const Schema& base, schema::PropertyList<> props) : Schema("", base, props) {} // Variant Schema(const std::vector& xs); // NOLINT(runtime/explicit) - Schema(std::string&& desc, const std::vector& xs); + Schema(std::string desc, const std::vector& xs); Schema(schema::BoxList props); // NOLINT(runtime/explicit) - Schema(std::string&& desc, schema::BoxList props); + Schema(std::string desc, schema::BoxList props); Schema(schema::BoxVec&& props); // NOLINT(runtime/explicit) - Schema(std::string&& desc, schema::BoxVec&& props); + Schema(std::string desc, schema::BoxVec&& props); // Interface - template ::value, int> = 0> + template , int> = 0> Schema(const T& value) : impl_(value.clone()) {} // NOLINT(runtime/explicit) Schema(schema::Interface* i) : impl_(i) { assert(impl_); } // NOLINT(runtime/explicit) Schema(std::shared_ptr i) : impl_(std::move(i)) { // NOLINT(runtime/explicit) @@ -211,19 +207,19 @@ class Schema : public schema::Interface { // Ignore Schema() : impl_(new schema::Ignore("")) {} - explicit Schema(std::string&& desc, JsonType t = JsonType::object) + explicit Schema(std::string desc, JsonType t = JsonType::object) : impl_(new schema::Ignore(std::move(desc), t)) {} // Primitives template - Schema(T* ptr, std::string&& desc) : impl_(make_schema(ptr, std::move(desc)).clone()) {} + Schema(T* ptr, std::string desc) : impl_(make_schema(ptr, std::move(desc)).clone()) {} template - Schema(T* ptr, const schema::Box& prototype, std::string&& desc) + Schema(T* ptr, const schema::Box& prototype, std::string desc) : impl_(make_schema(ptr, prototype, std::move(desc)).clone()) {} // FromJson template - Schema(T* ptr, JsonType t, std::string&& desc) + Schema(T* ptr, JsonType t, std::string desc) : impl_(new schema::FromJson(ptr, t, std::move(desc))) {} public: // Special diff --git a/fable/include/fable/schema/array.hpp b/fable/include/fable/schema/array.hpp index cfb7ed800..c59d71604 100644 --- a/fable/include/fable/schema/array.hpp +++ b/fable/include/fable/schema/array.hpp @@ -40,17 +40,17 @@ 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, std::string desc); + 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 - Array(Type* ptr, std::string&& desc) + Array(Type* ptr, std::string desc) : Array(ptr, make_prototype(), std::move(desc)) {} #endif @@ -173,9 +173,9 @@ class Array : public Base> { Type* ptr_{nullptr}; }; -template -Array make_schema(std::vector* ptr, const P& prototype, std::string&& desc) { - return Array(ptr, prototype, std::move(desc)); +template +Array make_schema(std::vector* ptr, P&& prototype, S&& desc) { + return Array(ptr, std::forward

(prototype), std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/boolean.hpp b/fable/include/fable/schema/boolean.hpp index ed3d695a3..4c4b840f7 100644 --- a/fable/include/fable/schema/boolean.hpp +++ b/fable/include/fable/schema/boolean.hpp @@ -35,7 +35,7 @@ class Boolean : public Base { public: // Types and Constructors using Type = bool; - Boolean(Type* ptr, std::string&& desc); + Boolean(Type* ptr, std::string desc); public: // Overrides Json json_schema() const override; @@ -51,7 +51,8 @@ class Boolean : public Base { Type* ptr_{nullptr}; }; -inline Boolean make_schema(bool* ptr, std::string&& desc) { return Boolean(ptr, std::move(desc)); } +template +inline Boolean make_schema(bool* ptr, S&& desc) { return Boolean(ptr, std::forward(desc)); } } // namespace schema } // namespace fable diff --git a/fable/include/fable/schema/confable.hpp b/fable/include/fable/schema/confable.hpp index 06bd0e835..66a4da2d6 100644 --- a/fable/include/fable/schema/confable.hpp +++ b/fable/include/fable/schema/confable.hpp @@ -37,19 +37,19 @@ class Confable; namespace schema { -template ::value, int> = 0> +template , int> = 0> class FromConfable : public Base> { public: // Types and Constructors using Type = T; - explicit FromConfable(std::string&& desc = "") { - schema_ = Type().schema(); + FromConfable(std::string desc = "") { + schema_ = Type().schema(); // NOLINT schema_.reset_ptr(); this->type_ = schema_.type(); this->desc_ = std::move(desc); } - FromConfable(Type* ptr, std::string&& desc) + FromConfable(Type* ptr, std::string desc) : Base>(ptr->schema().type(), std::move(desc)) , schema_(ptr->schema()) , ptr_(ptr) { @@ -103,10 +103,10 @@ class FromConfable : public Base> { Type* ptr_{nullptr}; }; -template -FromConfable make_schema(T* ptr, std::string&& desc) { +template +FromConfable make_schema(T* ptr, S&& desc) { assert(ptr != nullptr); - return FromConfable(ptr, std::move(desc)); + return FromConfable(ptr, std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/const.hpp b/fable/include/fable/schema/const.hpp index d4abdaf8b..8836f7f7a 100644 --- a/fable/include/fable/schema/const.hpp +++ b/fable/include/fable/schema/const.hpp @@ -37,19 +37,19 @@ 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, 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(); } #if 0 // This is defined in: fable/schema/magic.hpp - Const(const T& constant, std::string&& desc) + Const(const T& constant, std::string desc) : Const(constant, make_prototype(), std::move(desc)) {} #endif @@ -88,17 +88,14 @@ class Const : public Base> { const Type constant_; }; -template -Const make_const_schema(const T& constant, const P& prototype, std::string&& desc) { - return Const(constant, prototype, std::move(desc)); -} - -inline Const make_const_str(const std::string& constant, std::string&& desc) { - return Const(constant, std::move(desc)); +template +Const make_const_schema(const T& constant, P&& prototype, S&& desc) { + return Const(constant, std::forward

(prototype), std::forward(desc)); } -inline Const make_const_str(const char* constant, std::string&& desc) { - return Const(constant, std::move(desc)); +template +inline Const make_const_str(S1&& constant, S2&& desc) { + return Const(std::forward(constant), std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/duration.hpp b/fable/include/fable/schema/duration.hpp index edaf6cb66..791524339 100644 --- a/fable/include/fable/schema/duration.hpp +++ b/fable/include/fable/schema/duration.hpp @@ -39,18 +39,16 @@ class Duration : public Base> { public: // Types and Constructors using Type = std::chrono::duration; - template ::value && std::is_unsigned::value, int> = 0> - Duration(Type* ptr, std::string&& desc) + template && std::is_unsigned_v, int> = 0> + Duration(Type* ptr, std::string desc) : Base>(JsonType::number_unsigned, std::move(desc)), ptr_(ptr) {} - template ::value && std::is_signed::value, int> = 0> - Duration(Type* ptr, std::string&& desc) + template && std::is_signed_v, int> = 0> + Duration(Type* ptr, std::string desc) : Base>(JsonType::number_integer, std::move(desc)), ptr_(ptr) {} - template ::value, int> = 0> - Duration(Type* ptr, std::string&& desc) + template , int> = 0> + Duration(Type* ptr, std::string desc) : Base>(JsonType::number_float, std::move(desc)), ptr_(ptr) {} public: // Special @@ -186,10 +184,9 @@ class Duration : public Base> { Type* ptr_{nullptr}; }; -template -inline Duration make_schema(std::chrono::duration* ptr, - std::string&& desc) { - return Duration(ptr, std::move(desc)); +template +inline Duration make_schema(std::chrono::duration* ptr, S&& desc) { + return Duration(ptr, std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/enum.hpp b/fable/include/fable/schema/enum.hpp index 91a7c1158..5695ca7b8 100644 --- a/fable/include/fable/schema/enum.hpp +++ b/fable/include/fable/schema/enum.hpp @@ -40,7 +40,7 @@ class Enum : public Base> { public: // Types and Constructors using Type = T; - Enum(Type* ptr, std::string&& desc) + Enum(Type* ptr, std::string desc) : Base>(JsonType::string, std::move(desc)) , mapping_to_(enum_serialization()) , mapping_from_(enum_deserialization()) @@ -102,9 +102,9 @@ class Enum : public Base> { Type* ptr_{nullptr}; }; -template ::value, int> = 0> -inline Enum make_schema(T* ptr, std::string&& desc) { - return Enum(ptr, std::move(desc)); +template , int> = 0> +inline Enum make_schema(T* ptr, S&& desc) { + return Enum(ptr, std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/factory.hpp b/fable/include/fable/schema/factory.hpp index a7bf036da..de3395e7a 100644 --- a/fable/include/fable/schema/factory.hpp +++ b/fable/include/fable/schema/factory.hpp @@ -78,14 +78,14 @@ class FactoryBase : public Base { * * \see add_factory() */ - explicit FactoryBase(std::string&& desc = "") : Base(JsonType::object, std::move(desc)) {} + explicit FactoryBase(std::string desc = "") : Base(JsonType::object, std::move(desc)) {} - FactoryBase(std::string&& desc, FactoryPairList fs) + FactoryBase(std::string desc, FactoryPairList fs) : Base(JsonType::object, std::move(desc)), available_(std::move(fs)) { reset_schema(); } - FactoryBase(std::string&& desc, FactoryMap&& fs) + FactoryBase(std::string desc, FactoryMap&& fs) : Base(JsonType::object, std::move(desc)), available_(std::move(fs)) { reset_schema(); } @@ -229,8 +229,8 @@ class FactoryBase : public Base { * Most types inheriting from `Confable` will fulfill these requirements. */ template ::value && - std::is_convertible, T>::value), + std::enable_if_t<(std::is_default_constructible_v && + std::is_convertible_v, T>), int> = 0> void add_default_factory(const std::string& key) { add_factory(key, make_prototype().get_confable_schema(), [](const Conf& c) -> T { @@ -381,9 +381,9 @@ class Factory : public FactoryBase> { public: // Constructors using FactoryBase>::FactoryBase; - Factory(Type* ptr, std::string&& desc) : FactoryBase>(std::move(desc)), ptr_(ptr) {} + Factory(Type* ptr, std::string desc) : FactoryBase>(std::move(desc)), ptr_(ptr) {} - Factory(Type* ptr, std::string&& desc, FactoryMap&& fs) + Factory(Type* ptr, std::string desc, FactoryMap&& fs) : FactoryBase>(std::move(desc)), ptr_(ptr) { for (auto&& f : fs) { this->available_.insert(f); @@ -391,7 +391,7 @@ class Factory : public FactoryBase> { this->reset_schema(); } - Factory(Type* ptr, std::string&& desc, FactoryPairList fs) + Factory(Type* ptr, std::string desc, FactoryPairList fs) : FactoryBase>(std::move(desc)), ptr_(ptr) { for (auto&& f : fs) { this->available_.insert(f); diff --git a/fable/include/fable/schema/ignore.hpp b/fable/include/fable/schema/ignore.hpp index 4973345ca..5021518ca 100644 --- a/fable/include/fable/schema/ignore.hpp +++ b/fable/include/fable/schema/ignore.hpp @@ -44,7 +44,7 @@ namespace schema { class Ignore : public Base { public: // Constructors Ignore() : Base(JsonType::object, "ignored") {} - explicit Ignore(std::string&& desc, JsonType t = JsonType::object) : Base(t, std::move(desc)) {} + explicit Ignore(std::string desc, JsonType t = JsonType::object) : Base(t, std::move(desc)) {} public: // Overrides Json json_schema() const override { @@ -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/interface.hpp b/fable/include/fable/schema/interface.hpp index 0de49db10..4d0bd6cff 100644 --- a/fable/include/fable/schema/interface.hpp +++ b/fable/include/fable/schema/interface.hpp @@ -254,7 +254,7 @@ class Interface { * void foobar(S schema); */ template -using enable_if_schema_t = std::enable_if_t::value>; +using enable_if_schema_t = std::enable_if_t>; // ------------------------------------------------------------------------- // @@ -352,9 +352,9 @@ template class Base : public Interface { public: Base() = default; - Base(JsonType t, std::string&& desc) : type_(t), desc_(std::move(desc)) {} + Base(JsonType t, std::string desc) : type_(t), desc_(std::move(desc)) {} explicit Base(JsonType t) : type_(t) {} - explicit Base(std::string&& desc) : desc_(std::move(desc)) {} + explicit Base(std::string desc) : desc_(std::move(desc)) {} virtual ~Base() = default; Interface* clone() const override { return new CRTP(static_cast(*this)); } @@ -391,7 +391,7 @@ class Base : public Interface { void set_description(const std::string& s) override { desc_ = s; } void set_description(std::string&& s) { desc_ = std::move(s); } const std::string& description() const override { return desc_; } - CRTP description(std::string&& desc) && { + CRTP description(std::string desc) && { desc_ = std::move(desc); return std::move(*dynamic_cast(this)); } @@ -444,7 +444,7 @@ class Base : public Interface { * void foobar(T x); */ template -using enable_if_confable_t = std::enable_if_t::value>; +using enable_if_confable_t = std::enable_if_t>; /** * Use SFINAE mechanism to disable a template function when S is a subclass @@ -455,13 +455,13 @@ using enable_if_confable_t = std::enable_if_t::valu * void foobar(T x); */ template -using enable_if_not_confable_t = std::enable_if_t::value>; +using enable_if_not_confable_t = std::enable_if_t>; -template ::value, int> = 0> -auto make_prototype(std::string&& desc = ""); +template , int> = 0> +auto make_prototype(S&& desc = ""); -template ::value, int> = 0> -auto make_prototype(std::string&& desc = ""); +template , int> = 0> +auto make_prototype(S&& desc = ""); } // namespace schema } // namespace fable diff --git a/fable/include/fable/schema/json.hpp b/fable/include/fable/schema/json.hpp index 09ae6cfd3..fb7305eb1 100644 --- a/fable/include/fable/schema/json.hpp +++ b/fable/include/fable/schema/json.hpp @@ -48,7 +48,7 @@ class FromJson : public Base> { public: // Types and Constructors using Type = T; - FromJson(Type* ptr, JsonType t, std::string&& desc) + FromJson(Type* ptr, JsonType t, std::string desc) : Base>(t, std::move(desc)), ptr_(ptr) {} public: // Overrides @@ -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..449d04aa5 100644 --- a/fable/include/fable/schema/magic.hpp +++ b/fable/include/fable/schema/magic.hpp @@ -54,51 +54,50 @@ class Confable; namespace schema { template -Array::Array(std::vector* ptr, std::string&& desc) +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) { - return Array())>(ptr, std::move(desc)); +template +Array())> make_schema(std::vector* ptr, S&& desc) { + return Array())>(ptr, std::forward(desc)); } template -Const::Const(const T& constant, std::string&& desc) +Const::Const(const T& constant, std::string desc) : Const(constant, make_prototype(), std::move(desc)) {} -template -Const())> make_const_schema(const T& constant, std::string&& desc) { - return Const())>(constant, std::move(desc)); +template +Const())> make_const_schema(const T& constant, S&& desc) { + return Const())>(constant, std::forward(desc)); } template -Map::Map(std::map* ptr, std::string&& desc) +Map::Map(std::map* ptr, std::string desc) : Map(ptr, make_prototype(), std::move(desc)) {} -template +template Map())> make_schema(std::map* ptr, - std::string&& desc) { - return Map())>(ptr, std::move(desc)); + S&& desc) { + return Map())>(ptr, std::forward(desc)); } template -Optional::Optional(boost::optional* ptr, std::string&& desc) +Optional::Optional(boost::optional* ptr, std::string desc) : Optional(ptr, make_prototype(), std::move(desc)) {} -template -Optional())> make_schema(boost::optional* ptr, - std::string&& desc) { - return Optional())>(ptr, std::move(desc)); +template +Optional())> make_schema(boost::optional* ptr, S&& desc) { + return Optional())>(ptr, std::forward(desc)); } -template ::value, int>> -auto make_prototype(std::string&& desc) { - return FromConfable(std::move(desc)); +template , int>> +auto make_prototype(S&& desc) { + return FromConfable(std::forward(desc)); } -template ::value, int>> -auto make_prototype(std::string&& desc) { - return make_schema(static_cast(nullptr), std::move(desc)); +template , int>> +auto make_prototype(S&& desc) { + return make_schema(static_cast(nullptr), std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/map.hpp b/fable/include/fable/schema/map.hpp index 3d52a3418..08c8d6363 100644 --- a/fable/include/fable/schema/map.hpp +++ b/fable/include/fable/schema/map.hpp @@ -50,21 +50,21 @@ 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, std::string desc); + 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(); } #if 0 // This is defined in: fable/schema/magic.hpp - Map(Type* ptr, std::string&& desc) + Map(Type* ptr, std::string desc) : Map(ptr, make_prototype(), std::move(desc)) {} #endif @@ -188,9 +188,9 @@ class Map : public Base> { Type* ptr_{nullptr}; }; -template -Map make_schema(std::map* ptr, const P& prototype, std::string&& desc) { - return Map(ptr, prototype, std::move(desc)); +template +Map make_schema(std::map* ptr, P&& prototype, S&& desc) { + return Map(ptr, std::forward

(prototype), std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/number.hpp b/fable/include/fable/schema/number.hpp index 305ed5492..6c85fe8ee 100644 --- a/fable/include/fable/schema/number.hpp +++ b/fable/include/fable/schema/number.hpp @@ -40,16 +40,16 @@ class Number : public Base> { public: // Types and Constructors using Type = T; - template ::value && std::is_unsigned::value, int> = 0> - Number(Type* ptr, std::string&& desc) + template && std::is_unsigned_v, int> = 0> + Number(Type* ptr, std::string desc) : Base>(JsonType::number_unsigned, std::move(desc)), ptr_(ptr) {} - template ::value && std::is_signed::value, int> = 0> - Number(Type* ptr, std::string&& desc) + template && std::is_signed_v, int> = 0> + Number(Type* ptr, std::string desc) : Base>(JsonType::number_integer, std::move(desc)), ptr_(ptr) {} - template ::value, int> = 0> - Number(Type* ptr, std::string&& desc) + template , int> = 0> + Number(Type* ptr, std::string desc) : Base>(JsonType::number_float, std::move(desc)), ptr_(ptr) {} @@ -102,10 +102,9 @@ class Number : public Base> { Type* ptr_{nullptr}; }; -template ::value && !std::is_enum::value, int> = 0> -inline Number make_schema(T* ptr, std::string&& desc) { - return Number(ptr, std::move(desc)); +template && !std::is_enum_v, int> = 0> +inline Number make_schema(T* ptr, S&& desc) { + return Number(ptr, std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/optional.hpp b/fable/include/fable/schema/optional.hpp index ae67180db..a6938ed83 100644 --- a/fable/include/fable/schema/optional.hpp +++ b/fable/include/fable/schema/optional.hpp @@ -39,17 +39,17 @@ 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, std::string desc); + Optional(Type* ptr, PrototypeSchema prototype, std::string desc) + : Base>(prototype.type(), std::move(desc)), prototype_(std::move(prototype)), ptr_(ptr) { prototype_.reset_ptr(); } #if 0 // This is defined in: fable/schema/magic.hpp - Optional(Type* ptr, std::string&& desc) + Optional(Type* ptr, std::string desc) : Optional(ptr, make_prototype(), std::move(desc)) {} #endif @@ -112,9 +112,9 @@ class Optional : public Base> { Type* ptr_{nullptr}; }; -template -Optional make_schema(boost::optional* ptr, const P& prototype, std::string&& desc) { - return Optional(ptr, prototype, std::move(desc)); +template +Optional make_schema(boost::optional* ptr, P&& prototype, S&& desc) { + return Optional(ptr, std::forward

(prototype), std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/passthru.hpp b/fable/include/fable/schema/passthru.hpp index 78ef45244..b5427c05d 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(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,14 @@ class Passthru : public Base> { Type* ptr_{nullptr}; }; -inline Passthru make_schema(Conf* ptr, std::string&& desc) { - return Passthru(ptr, Ignore(), std::move(desc)); +template +inline Passthru make_schema(Conf* ptr, S&& desc) { + return Passthru(ptr, Ignore(), std::forward(desc)); } -template -Passthru

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

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

make_schema(Conf* ptr, P&& prototype, S&& desc) { + return Passthru

(ptr, std::forward

(prototype), std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/path.hpp b/fable/include/fable/schema/path.hpp index b17536747..69e26811c 100644 --- a/fable/include/fable/schema/path.hpp +++ b/fable/include/fable/schema/path.hpp @@ -71,7 +71,7 @@ class Path : public Base { NotDir, /// path does not exist or is a file }; - Path(Type* ptr, std::string&& desc) : Base(JsonType::string, std::move(desc)), ptr_(ptr) {} + Path(Type* ptr, std::string desc) : Base(JsonType::string, std::move(desc)), ptr_(ptr) {} public: // Special /** @@ -213,8 +213,9 @@ class Path : public Base { Type* ptr_{nullptr}; }; -inline Path make_schema(boost::filesystem::path* ptr, std::string&& desc) { - return Path(ptr, std::move(desc)); +template +inline Path make_schema(boost::filesystem::path* ptr, S&& desc) { + return Path(ptr, std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/string.hpp b/fable/include/fable/schema/string.hpp index 5d3ba12a0..19a4d72f5 100644 --- a/fable/include/fable/schema/string.hpp +++ b/fable/include/fable/schema/string.hpp @@ -65,7 +65,7 @@ class String : public Base { public: // Types and Constructors using Type = std::string; - String(Type* ptr, std::string&& desc) : Base(JsonType::string, std::move(desc)), ptr_(ptr) {} + String(Type* ptr, std::string desc) : Base(JsonType::string, std::move(desc)), ptr_(ptr) {} public: // Special /** @@ -261,8 +261,9 @@ class String : public Base { Type* ptr_{nullptr}; }; -inline String make_schema(std::string* ptr, std::string&& desc) { - return String(ptr, std::move(desc)); +template +inline String make_schema(std::string* ptr, S&& desc) { + return String(ptr, std::forward(desc)); } } // namespace schema diff --git a/fable/include/fable/schema/struct.hpp b/fable/include/fable/schema/struct.hpp index efa95ac2e..ad6013dec 100644 --- a/fable/include/fable/schema/struct.hpp +++ b/fable/include/fable/schema/struct.hpp @@ -55,7 +55,7 @@ template using PropertyList = std::initializer_list>; template -using enable_if_property_list_t = std::enable_if_t, T>::value>; +using enable_if_property_list_t = std::enable_if_t, T>>; /** * Struct maintains a key-value mapping, where the list of keys is usually @@ -70,9 +70,9 @@ using enable_if_property_list_t = std::enable_if_t, */ class Struct : public Base { public: // Constructors - explicit Struct(std::string&& desc = "") : Base(JsonType::object, std::move(desc)) {} + explicit Struct(std::string desc = "") : Base(JsonType::object, std::move(desc)) {} - Struct(std::string&& desc, PropertyList props) : Base(JsonType::object, std::move(desc)) { + Struct(std::string desc, PropertyList props) : Base(JsonType::object, std::move(desc)) { set_properties(props); } @@ -103,7 +103,7 @@ class Struct : public Base { * will internally call this->schema_impl(), which will lead to an * infinite recursion! Instead, call Base::schema_impl(). */ - Struct(std::string&& desc, const Box& base, PropertyList props) + Struct(std::string desc, const Box& base, PropertyList props) : Struct(*base.template as()) { desc_ = std::move(desc); set_properties(props); @@ -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..7630b547f 100644 --- a/fable/include/fable/schema/variant.hpp +++ b/fable/include/fable/schema/variant.hpp @@ -57,11 +57,11 @@ using BoxList = std::initializer_list; class Variant : public Interface { public: // Constructors Variant(std::initializer_list vec) : Variant("", vec) {} - Variant(std::string&& desc, std::initializer_list vec) + Variant(std::string desc, std::initializer_list vec) : Variant(std::move(desc), std::vector(vec)) {} Variant(std::vector&& vec) : Variant("", std::move(vec)) {} // NOLINT(runtime/explicit) - Variant(std::string&& desc, std::vector&& vec); + Variant(std::string desc, std::vector&& vec); public: // Base Interface* clone() const override { return new Variant(*this); } @@ -85,7 +85,7 @@ class Variant : public Interface { void set_description(const std::string& s) override { desc_ = s; } void set_description(std::string&& s) { desc_ = std::move(s); } const std::string& description() const override { return desc_; } - Variant description(std::string&& desc) && { + Variant description(std::string desc) && { desc_ = std::move(desc); return std::move(*this); } @@ -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 diff --git a/fable/src/fable/schema.cpp b/fable/src/fable/schema.cpp index 5f3a6f553..72e662b72 100644 --- a/fable/src/fable/schema.cpp +++ b/fable/src/fable/schema.cpp @@ -45,13 +45,13 @@ BoxVec to_box_vec(const std::vector& xs) { // Variant constructions: Schema::Schema(const std::vector& xs) : impl_(new Variant(to_box_vec(xs))) {} -Schema::Schema(std::string&& desc, const std::vector& xs) +Schema::Schema(std::string desc, const std::vector& xs) : impl_(new Variant(std::move(desc), to_box_vec(xs))) {} Schema::Schema(schema::BoxList props) : impl_(new Variant(props)) {} -Schema::Schema(std::string&& desc, schema::BoxList props) +Schema::Schema(std::string desc, schema::BoxList props) : impl_(new Variant(std::move(desc), props)) {} Schema::Schema(schema::BoxVec&& props) : impl_(new Variant(std::move(props))) {} -Schema::Schema(std::string&& desc, schema::BoxVec&& props) +Schema::Schema(std::string desc, schema::BoxVec&& props) : impl_(new Variant(std::move(desc), std::move(props))) {} } // namespace fable diff --git a/fable/src/fable/schema/boolean.cpp b/fable/src/fable/schema/boolean.cpp index a27404f4f..dc4ab312f 100644 --- a/fable/src/fable/schema/boolean.cpp +++ b/fable/src/fable/schema/boolean.cpp @@ -28,7 +28,7 @@ namespace fable { namespace schema { -Boolean::Boolean(Boolean::Type* ptr, std::string&& desc) +Boolean::Boolean(Boolean::Type* ptr, std::string desc) : Base(JsonType::boolean, std::move(desc)), ptr_(ptr) {} Json Boolean::json_schema() const { diff --git a/fable/src/fable/schema/factory_advanced_test.cpp b/fable/src/fable/schema/factory_advanced_test.cpp index a655ef3f4..99f5b89d3 100644 --- a/fable/src/fable/schema/factory_advanced_test.cpp +++ b/fable/src/fable/schema/factory_advanced_test.cpp @@ -119,7 +119,7 @@ class Random { class DistributionFactory : public fable::schema::Factory { public: - DistributionFactory(DistributionPtr* ptr, std::string&& desc) + DistributionFactory(DistributionPtr* ptr, std::string desc) : fable::schema::Factory(ptr, std::move(desc)) { this->set_factory_key("binding"); this->set_args_key(""); diff --git a/fable/src/fable/schema/variant.cpp b/fable/src/fable/schema/variant.cpp index 3694351f9..2d9e8c1f8 100644 --- a/fable/src/fable/schema/variant.cpp +++ b/fable/src/fable/schema/variant.cpp @@ -34,7 +34,7 @@ namespace fable { namespace schema { -Variant::Variant(std::string&& desc, std::vector&& vec) +Variant::Variant(std::string desc, std::vector&& vec) : desc_(std::move(desc)), schemas_(std::move(vec)) { assert(!schemas_.empty());