1 /** 2 * Copyright 2019 Huawei Technologies Co., Ltd 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef MINDSPORE_CCSRC_UTILS_CONTRACT_H 18 #define MINDSPORE_CCSRC_UTILS_CONTRACT_H 19 #include <string> 20 #include <exception> 21 #include <memory> 22 #include <utility> 23 #include <type_traits> 24 #include "utils/log_adapter.h" 25 26 namespace mindspore { 27 class ContractError : public std::logic_error { 28 public: ContractError(const std::string & msg)29 explicit ContractError(const std::string &msg) : std::logic_error(msg) {} ContractError(const char * msg)30 explicit ContractError(const char *msg) : std::logic_error(msg) {} 31 ~ContractError() override = default; 32 }; 33 34 struct Signatory { 35 LocationInfo location_info; 36 const char *extra_info; 37 }; 38 39 struct NotNullRule { 40 template <class T> CheckNotNullRule41 constexpr static bool Check(const T &val) { 42 return val != nullptr; 43 } DescNotNullRule44 constexpr static const char *Desc() { return " must not be null"; } 45 }; 46 template <class T, class R, class E = void> 47 class EnsuresAccess {}; 48 49 template <class T> 50 using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>; 51 52 template <class T, class R> 53 class Ensures : public EnsuresAccess<T, R> { 54 public: Ensures(T v,const Signatory & signatory)55 Ensures(T v, const Signatory &signatory) : value_(v) { 56 if (!R::Check(value_)) { 57 LogStream contract_stream; 58 contract_stream << "contract error: " << signatory.extra_info << R::Desc(); 59 LogWriter(signatory.location_info, EXCEPTION, SUBMODULE_ID, ArgumentError) ^ contract_stream; 60 } 61 } 62 template <class O, typename = std::enable_if_t<std::is_convertible_v<O, T>>> Ensures(const Ensures<O,R> & other)63 Ensures(const Ensures<O, R> &other) : value_(other.get()) {} 64 ~Ensures() = default; 65 get()66 const T get() const { return value_; } get()67 T &get() { return value_; } 68 T()69 operator const T() const { return value_; } 70 71 T value_; 72 }; 73 74 template <class T, class R> 75 class EnsuresAccess<T, R, std::enable_if_t<std::is_pointer_v<std::remove_cv_t<T>>>> { 76 public: 77 T operator->() const { 78 auto ptr = static_cast<const Ensures<T, R> *>(this)->get(); 79 return ptr; 80 } 81 }; 82 83 template <typename T> 84 struct IsSharedPtr : std::false_type {}; 85 template <typename T> 86 struct IsSharedPtr<std::shared_ptr<T>> : std::true_type {}; 87 template <typename T> 88 struct IsSharedPtr<const std::shared_ptr<T> &> : std::true_type {}; 89 90 template <class T, class R> 91 class EnsuresAccess<T, R, std::enable_if_t<IsSharedPtr<T>::value>> { 92 using element_type = typename std::remove_cv_t<std::remove_reference_t<T>>::element_type; 93 94 public: 95 element_type *operator->() const { 96 auto ptr = static_cast<const Ensures<T, R> *>(this)->get(); 97 return ptr.get(); 98 } 99 }; 100 101 template <class T, class R> 102 using Expects = Ensures<T, R>; 103 template <class T> 104 using NotNull = Ensures<T, NotNullRule>; 105 #define ENSURE(_v, _rule) Ensures<decltype(_v), _rule>(_v, {{__FILE__, __LINE__, __FUNCTION__}, #_v}) 106 #define NOT_NULL(_v) ENSURE(_v, NotNullRule) 107 } // namespace mindspore 108 #endif // MINDSPORE_CCSRC_UTILS_CONTRACT_H 109