00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #pragma once
00018
00019 #include "AITypes.h"
00020 #include "AIAssert.hpp"
00021 #include "IAILiteralString.h"
00022
00057 namespace ai
00058 {
00059 namespace Contract
00060 {
00061 constexpr ai::LiteralString kDefaultPreconditionMsg {"Failed Precondition"};
00062 constexpr ai::LiteralString kDefaultPostconditionMsg {"Failed Postcondition"};
00063
00067 struct Violation : public ai::LogicError
00068 {
00069 explicit Violation(const char* message) : ai::LogicError(kBadParameterErr, message)
00070 {
00071 }
00072 };
00073
00077 struct AssertPolicy {};
00078 struct ThrowPolicy {};
00079 struct AssertAndThrowPolicy {};
00080
00084 template <typename T>
00085 void Check(T condition, const char* msg, AssertPolicy)
00086 {
00087 AIMsgAssert(condition, msg);
00088 }
00089
00090 template <typename T>
00091 constexpr void Check(T condition, const char* msg, ThrowPolicy)
00092 {
00093 if (!condition)
00094 {
00095 throw Violation{msg};
00096 }
00097 }
00098
00099 template <typename T>
00100 void Check(T condition, const char* msg, AssertAndThrowPolicy)
00101 {
00102 if (!condition)
00103 {
00104 AIMsgAssert(false, msg);
00105 throw Violation{msg};
00106 }
00107 }
00108
00109 }
00110
00111 namespace ContractPolicy
00112 {
00113
00114 constexpr Contract::AssertPolicy kAssert {};
00115 constexpr Contract::ThrowPolicy kThrow {};
00116 constexpr Contract::AssertAndThrowPolicy kAssertAndThrow {};
00117
00118 }
00119
00120 template <typename T, typename Policy = Contract::ThrowPolicy>
00121 constexpr void Expects(T condition, const char* msg = Contract::kDefaultPreconditionMsg, Policy policy = ContractPolicy::kThrow)
00122 {
00123 Contract::Check(condition, msg, policy);
00124 }
00125
00126 template <typename T, typename Policy>
00127 constexpr void Expects(T condition, Policy policy)
00128 {
00129 Contract::Check(condition, Contract::kDefaultPreconditionMsg, policy);
00130 }
00131
00132 template <typename T, typename Policy = Contract::ThrowPolicy>
00133 constexpr void Ensures(T condition, const char* msg = Contract::kDefaultPostconditionMsg, Policy policy = ContractPolicy::kThrow)
00134 {
00135 Contract::Check(condition, msg, policy);
00136 }
00137
00138 template <typename T, typename Policy>
00139 constexpr void Ensures(T condition, Policy policy)
00140 {
00141 Contract::Check(condition, Contract::kDefaultPostconditionMsg, policy);
00142 }
00143
00144 template <typename T, typename Policy = Contract::ThrowPolicy>
00145 constexpr void EnsureRange(const T& value, const char* msg = Contract::kDefaultPostconditionMsg, Policy policy = ContractPolicy::kThrow)
00146 {
00147 Ensures(value > T::kUnknown && value < T::kLast, msg, policy);
00148 }
00149
00150
00151 }