Samuel Jaffe пре 9 година
комит
07f717fab2
2 измењених фајлова са 312 додато и 0 уклоњено
  1. 61 0
      prototype_factory.hpp
  2. 251 0
      resource_factory.xcodeproj/project.pbxproj

+ 61 - 0
prototype_factory.hpp

@@ -0,0 +1,61 @@
+//
+//  polymorphic_factory.hpp
+//  resource_factory
+//
+//  Created by Sam Jaffe on 8/14/16.
+//
+
+#pragma once
+
+#include <functional>
+#include <unordered_map>
+
+/*
+ * An instance prototype factory factory.
+ * The purpose of this object is a prefab for situations where you do not
+ * know, necessarily, at compile time all posible types inheriting from the
+ * base class. An example of this is in a game, you may have a Mob class.
+ * Mob may be instantiated as an Orc, Goblin, Slime, or Knight, but you don't
+ * know the exhaustive list, and the overhead for implementing an override
+ * for every single type is wasteful. With this object, you can initialize
+ * implementations from a string ID, and some parameters required.
+ * For example:
+ *
+ * class Monster { ... };
+ * class MonsterPrototype : public Monster {
+ *   public: Monster operator()(...) const { ... }
+ * };
+ * using MonsterGenerator = prototype_factory<Monster, ...>;
+ * MonsterGenerator::bind("Orc", MonsterPrototype("resources/orc.proto"));
+ *
+ * -----
+ *
+ * This can also be used as a generator for polymorphic types, optionally
+ * through a plugin system. This would allow a library consumer to define
+ * extensions to some polymorphic class, such as a Widget, and use built in
+ * features of the library to instantiate it. For example:
+ *
+ * class Widget { ... };
+ * class Button : public Widget { ... };
+ * using WidgetGenerator = prototype_factory<std::unique_ptr<Widget>, ...>;
+ * WidgetGenerator::bind("Button",
+ *                       [](...) { return std::make_unique<Button>(...); });
+ */
+template <typename Base, typename... Args>
+class prototype_factory {
+public:
+  using rval_t = Base;
+  using producer = std::function<rval_t(Args &&...)>;
+  
+  static rval_t get(std::string const & type_id, Args &&... args) {
+    auto it = _factories.find(type_id);
+    if (it == _factories.end()) { return rval_t(); }
+    else { return (it->second)(std::forward<Args>(args)...); }
+  }
+  
+  static bool bind(std::string const & type_id, producer p) {
+    return _factories.insert(std::make_pair(type_id, p)).second;
+  }
+private:
+  static std::unordered_map<std::string, producer> _factories;
+};

+ 251 - 0
resource_factory.xcodeproj/project.pbxproj

@@ -0,0 +1,251 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CD35DCEC1D612D0400BE3686 /* prototype_factory.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CD35DCEB1D612D0400BE3686 /* prototype_factory.hpp */; };
+		CD35DCEF1D612F0100BE3686 /* _.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD35DCED1D612F0100BE3686 /* _.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		CD35DCDD1D612CCD00BE3686 /* libresource_factory.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libresource_factory.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD35DCEB1D612D0400BE3686 /* prototype_factory.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = prototype_factory.hpp; sourceTree = "<group>"; };
+		CD35DCED1D612F0100BE3686 /* _.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = _.cpp; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		CD35DCDA1D612CCD00BE3686 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		CD35DCD41D612CCD00BE3686 = {
+			isa = PBXGroup;
+			children = (
+				CD35DCEB1D612D0400BE3686 /* prototype_factory.hpp */,
+				CD35DCED1D612F0100BE3686 /* _.cpp */,
+				CD35DCDE1D612CCD00BE3686 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		CD35DCDE1D612CCD00BE3686 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CD35DCDD1D612CCD00BE3686 /* libresource_factory.dylib */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		CD35DCDB1D612CCD00BE3686 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD35DCEC1D612D0400BE3686 /* prototype_factory.hpp in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		CD35DCDC1D612CCD00BE3686 /* resource_factory */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CD35DCE81D612CCD00BE3686 /* Build configuration list for PBXNativeTarget "resource_factory" */;
+			buildPhases = (
+				CD35DCD91D612CCD00BE3686 /* Sources */,
+				CD35DCDA1D612CCD00BE3686 /* Frameworks */,
+				CD35DCDB1D612CCD00BE3686 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = resource_factory;
+			productName = resource_factory;
+			productReference = CD35DCDD1D612CCD00BE3686 /* libresource_factory.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CD35DCD51D612CCD00BE3686 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0720;
+				ORGANIZATIONNAME = "Sam Jaffe";
+				TargetAttributes = {
+					CD35DCDC1D612CCD00BE3686 = {
+						CreatedOnToolsVersion = 7.2.1;
+					};
+				};
+			};
+			buildConfigurationList = CD35DCD81D612CCD00BE3686 /* Build configuration list for PBXProject "resource_factory" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = CD35DCD41D612CCD00BE3686;
+			productRefGroup = CD35DCDE1D612CCD00BE3686 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				CD35DCDC1D612CCD00BE3686 /* resource_factory */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CD35DCD91D612CCD00BE3686 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD35DCEF1D612F0100BE3686 /* _.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CD35DCE61D612CCD00BE3686 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		CD35DCE71D612CCD00BE3686 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		CD35DCE91D612CCD00BE3686 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXECUTABLE_PREFIX = lib;
+				GCC_ENABLE_CPP_EXCEPTIONS = YES;
+				GCC_ENABLE_CPP_RTTI = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		CD35DCEA1D612CCD00BE3686 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXECUTABLE_PREFIX = lib;
+				GCC_ENABLE_CPP_EXCEPTIONS = YES;
+				GCC_ENABLE_CPP_RTTI = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CD35DCD81D612CCD00BE3686 /* Build configuration list for PBXProject "resource_factory" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD35DCE61D612CCD00BE3686 /* Debug */,
+				CD35DCE71D612CCD00BE3686 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CD35DCE81D612CCD00BE3686 /* Build configuration list for PBXNativeTarget "resource_factory" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD35DCE91D612CCD00BE3686 /* Debug */,
+				CD35DCEA1D612CCD00BE3686 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = CD35DCD51D612CCD00BE3686 /* Project object */;
+}