Explorar o código

Adding test cases.
Adding exception constructor.
Adding valid-range static_assert.

Samuel Jaffe %!s(int64=8) %!d(string=hai) anos
pai
achega
aaa4046466
Modificáronse 3 ficheiros con 275 adicións e 78 borrados
  1. 54 47
      bound_number.hpp
  2. 56 0
      bound_number.t.h
  3. 165 31
      limit.xcodeproj/project.pbxproj

+ 54 - 47
bound_number.hpp

@@ -8,57 +8,64 @@
 
 #pragma once
 
+#include <stdexcept>
+
+struct {} check_bounds;
+using check_bounds_t = decltype(check_bounds);
+
 template <class Tp, Tp MINIMUM_VALUE, Tp MAXIMUM_VALUE>
 class bound_number final {
 private:
 public:
-    typedef Tp value_type;
-    
-    bound_number() = default;
-    bound_number(const bound_number& other) = default;
-    bound_number(bound_number&& other) = default;
-    bound_number& operator=(const bound_number& other) = default;
-    bound_number& operator=(bound_number&& other) = default;
-    ~bound_number() = default;
-
-    bound_number(const Tp value) :
-    value(value) {
-        
-    }
-    
-    bound_number& operator --() {
-        if (value > MINIMUM_VALUE) {
-            --value;
-        }
-        return *this;
-    }
-    
-    bound_number& operator ++() {
-        if (value < MAXIMUM_VALUE) {
-            ++value;
-        }
-        return *this;
-    }
-    
-    bound_number operator --(int) {
-        bound_number tmp = *this;
-        if (value > MINIMUM_VALUE) {
-            --value;
-        }
-        return tmp;
-    }
-    
-    bound_number operator ++(int) {
-        bound_number tmp = *this;
-        if (value < MAXIMUM_VALUE) {
-            ++value;
-        }
-        return tmp;
-    }
-    
-    operator Tp() const {
-        return value;
+  static_assert(MINIMUM_VALUE <= MAXIMUM_VALUE, "The minimum value must be less than or equal to the maximum");
+  
+  typedef Tp value_type;
+  static constexpr const value_type min = MINIMUM_VALUE;
+  static constexpr const value_type max = MAXIMUM_VALUE;
+  
+  bound_number() = default;
+  bound_number(const bound_number& other) = default;
+  bound_number(bound_number&& other) = default;
+  bound_number& operator=(const bound_number& other) = default;
+  bound_number& operator=(bound_number&& other) = default;
+  ~bound_number() = default;
+  
+  bound_number(Tp const & val) :
+  value(std::max(MINIMUM_VALUE, std::min(MAXIMUM_VALUE, val))) {
+  }
+  
+  bound_number(check_bounds_t, Tp const & val) :
+  value(val) {
+    if ( val < MINIMUM_VALUE || MAXIMUM_VALUE < val ) {
+      throw std::out_of_range{"Must construct a value within range"};
     }
+  }
+  
+  bound_number& operator --() {
+    if (min < value) { --value; }
+    return *this;
+  }
+  
+  bound_number& operator ++() {
+    if (value < max) { ++value; }
+    return *this;
+  }
+  
+  bound_number operator --(int) {
+    bound_number tmp = *this;
+    operator--();
+    return tmp;
+  }
+  
+  bound_number operator ++(int) {
+    bound_number tmp = *this;
+    operator++();
+    return tmp;
+  }
+  
+  operator Tp() const {
+    return value;
+  }
 private:
-    Tp value;
+  Tp value;
 };

+ 56 - 0
bound_number.t.h

@@ -0,0 +1,56 @@
+//
+//  bound_number.t.h
+//  limit
+//
+//  Created by Sam Jaffe on 2/3/17.
+//
+#pragma once
+
+#include "bound_number.hpp"
+
+#include <cxxtest/TestSuite.h>
+
+class bound_number_TestSuite : public CxxTest::TestSuite {
+public:
+  using number_t = bound_number<int, -5, +7>;
+  
+//  Fails to compile because of well-ordered principle
+//  void test_bounds_compiler_error() {
+//    bound_number<int, 0, -1>(0);
+//  }
+  
+  void test_number_construct_inbounds() {
+    number_t n{0};
+    TS_ASSERT_EQUALS(n, 0);
+  }
+  
+  void test_number_validate_oob_low() {
+    TS_ASSERT_THROWS((number_t{check_bounds, -6}), std::out_of_range);
+  }
+
+  void test_number_validate_oob_high() {
+    TS_ASSERT_THROWS((number_t{check_bounds, +8}), std::out_of_range);
+  }
+
+  void test_number_cannot_construct_oob_low() {
+    number_t n{-6};
+    TS_ASSERT_EQUALS(n, number_t::min);
+  }
+  
+  void test_number_cannot_construct_oob_high() {
+    number_t n{10};
+    TS_ASSERT_EQUALS(n, number_t::max);
+  }
+  
+  void test_number_cannot_increment_above_limit() {
+    number_t n{+7};
+    TS_ASSERT_EQUALS(n++, number_t::max);
+    TS_ASSERT_EQUALS(n, number_t::max);
+  }
+
+  void test_number_cannot_decrement_below_limit() {
+    number_t n{-5};
+    TS_ASSERT_EQUALS(n--, number_t::min);
+    TS_ASSERT_EQUALS(n, number_t::min);
+  }
+};

+ 165 - 31
limit.xcodeproj/project.pbxproj

@@ -6,15 +6,45 @@
 	objectVersion = 46;
 	objects = {
 
+/* Begin PBXBuildFile section */
+		CDFB746A1E451F94007D4841 /* limit_tc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDFB745D1E451F61007D4841 /* limit_tc.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		CDFB74611E451F72007D4841 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
 /* Begin PBXFileReference section */
 		0E5DFDCB1BB4D3360063976E /* bound_number.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = bound_number.hpp; sourceTree = "<group>"; };
+		CDFB745D1E451F61007D4841 /* limit_tc.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = limit_tc.cpp; sourceTree = "<group>"; };
+		CDFB745E1E451F61007D4841 /* bound_number.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bound_number.t.h; sourceTree = "<group>"; };
+		CDFB74631E451F72007D4841 /* limit_tc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = limit_tc; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
+/* Begin PBXFrameworksBuildPhase section */
+		CDFB74601E451F72007D4841 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
 /* Begin PBXGroup section */
 		0E5DFDC51BB4D3360063976E = {
 			isa = PBXGroup;
 			children = (
-				0E5DFDCB1BB4D3360063976E /* bound_number.hpp */,
+				CDFB745B1E451F42007D4841 /* src */,
+				CDFB745C1E451F45007D4841 /* test */,
 				0E5DFE1C1BB4DB740063976E /* Products */,
 			);
 			sourceTree = "<group>";
@@ -22,34 +52,61 @@
 		0E5DFE1C1BB4DB740063976E /* Products */ = {
 			isa = PBXGroup;
 			children = (
+				CDFB74631E451F72007D4841 /* limit_tc */,
 			);
 			name = Products;
 			sourceTree = "<group>";
 		};
+		CDFB745B1E451F42007D4841 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				0E5DFDCB1BB4D3360063976E /* bound_number.hpp */,
+			);
+			name = src;
+			sourceTree = "<group>";
+		};
+		CDFB745C1E451F45007D4841 /* test */ = {
+			isa = PBXGroup;
+			children = (
+				CDFB745E1E451F61007D4841 /* bound_number.t.h */,
+				CDFB745D1E451F61007D4841 /* limit_tc.cpp */,
+			);
+			name = test;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
-/* Begin PBXLegacyTarget section */
-		0E5DFDCA1BB4D3360063976E /* limit */ = {
-			isa = PBXLegacyTarget;
-			buildArgumentsString = "$(ACTION)";
-			buildConfigurationList = 0E5DFDCD1BB4D3360063976E /* Build configuration list for PBXLegacyTarget "limit" */;
+/* Begin PBXNativeTarget section */
+		CDFB74621E451F72007D4841 /* limit_tc */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CDFB74671E451F72007D4841 /* Build configuration list for PBXNativeTarget "limit_tc" */;
 			buildPhases = (
+				CDFB746B1E451FAB007D4841 /* ShellScript */,
+				CDFB745F1E451F72007D4841 /* Sources */,
+				CDFB74601E451F72007D4841 /* Frameworks */,
+				CDFB74611E451F72007D4841 /* CopyFiles */,
+			);
+			buildRules = (
 			);
-			buildToolPath = /usr/bin/make;
-			buildWorkingDirectory = "/Users/leumasjaffe/Documents/Programming/XTools Workspace/C:C++/misc/math/limit";
 			dependencies = (
 			);
-			name = limit;
-			passBuildSettingsInEnvironment = 1;
-			productName = limit;
+			name = limit_tc;
+			productName = limit_tc;
+			productReference = CDFB74631E451F72007D4841 /* limit_tc */;
+			productType = "com.apple.product-type.tool";
 		};
-/* End PBXLegacyTarget section */
+/* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
 		0E5DFDC61BB4D3360063976E /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
 				LastUpgradeCheck = 0720;
+				TargetAttributes = {
+					CDFB74621E451F72007D4841 = {
+						CreatedOnToolsVersion = 7.2.1;
+					};
+				};
 			};
 			buildConfigurationList = 0E5DFDC91BB4D3360063976E /* Build configuration list for PBXProject "limit" */;
 			compatibilityVersion = "Xcode 3.2";
@@ -63,11 +120,40 @@
 			projectDirPath = "";
 			projectRoot = "";
 			targets = (
-				0E5DFDCA1BB4D3360063976E /* limit */,
+				CDFB74621E451F72007D4841 /* limit_tc */,
 			);
 		};
 /* End PBXProject section */
 
+/* Begin PBXShellScriptBuildPhase section */
+		CDFB746B1E451FAB007D4841 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(SRCROOT)/bound_number.t.h",
+			);
+			outputPaths = (
+				"$(SRCROOT)/limit_tc.cpp",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "cxxtestgen --error-printer -o limit_tc.cpp bound_number.t.h";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CDFB745F1E451F72007D4841 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CDFB746A1E451F94007D4841 /* limit_tc.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
 /* Begin XCBuildConfiguration section */
 		0E5DFDC71BB4D3360063976E /* Debug */ = {
 			isa = XCBuildConfiguration;
@@ -91,30 +177,79 @@
 			};
 			name = Release;
 		};
-		0E5DFDCE1BB4D3360063976E /* Debug */ = {
+		CDFB74681E451F72007D4841 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-				DEBUGGING_SYMBOLS = YES;
+				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 = "-";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_ENABLE_FIX_AND_CONTINUE = YES;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
-				OTHER_CFLAGS = "";
-				OTHER_LDFLAGS = "";
-				PRODUCT_NAME = limit;
+				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;
+				HEADER_SEARCH_PATHS = /usr/local/include/;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Debug;
 		};
-		0E5DFDCF1BB4D3360063976E /* Release */ = {
+		CDFB74691E451F72007D4841 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				COPY_PHASE_STRIP = YES;
+				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";
-				GCC_ENABLE_FIX_AND_CONTINUE = NO;
-				OTHER_CFLAGS = "";
-				OTHER_LDFLAGS = "";
-				PRODUCT_NAME = limit;
+				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;
+				HEADER_SEARCH_PATHS = /usr/local/include/;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
 		};
@@ -130,14 +265,13 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		0E5DFDCD1BB4D3360063976E /* Build configuration list for PBXLegacyTarget "limit" */ = {
+		CDFB74671E451F72007D4841 /* Build configuration list for PBXNativeTarget "limit_tc" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				0E5DFDCE1BB4D3360063976E /* Debug */,
-				0E5DFDCF1BB4D3360063976E /* Release */,
+				CDFB74681E451F72007D4841 /* Debug */,
+				CDFB74691E451F72007D4841 /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
 	};