1 /** 2 * Copyright 2023 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 FuncObject KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <exception> 18 #include <typeinfo> 19 #include <type_traits> 20 #include <typeindex> 21 #include <utility> 22 #include "utils/log_adapter.h" 23 24 namespace mindspore::runtime { 25 class FuncObject { 26 public: 27 FuncObject() = default; 28 template <typename T> FuncObject(const T & value)29 explicit FuncObject(const T &value) 30 : object_(new Object<typename std::remove_cv_t<typename std::decay_t<const T>>>(value)) {} FuncObject(const FuncObject & other)31 FuncObject(const FuncObject &other) : object_(other.object_ ? other.object_->clone() : nullptr) {} FuncObject(FuncObject && other)32 FuncObject(FuncObject &&other) : object_(other.object_) { other.object_ = nullptr; } 33 template <typename T> FuncObject(T && value)34 FuncObject(T &&value) : object_(new Object<typename std::decay_t<T>>(static_cast<T &&>(value))) {} 35 ~FuncObject()36 ~FuncObject() { 37 delete object_; 38 object_ = nullptr; 39 } 40 41 public: swap(FuncObject & rhs)42 FuncObject &swap(FuncObject &rhs) { 43 std::swap(object_, rhs.object_); 44 return *this; 45 } 46 47 template <typename T> 48 FuncObject &operator=(T &&rhs) { 49 // cppcheck-suppress * 50 (void)FuncObject(static_cast<T &&>(rhs)).swap(*this); 51 return *this; 52 } 53 type()54 const std::type_info &type() const { return object_ ? object_->type() : typeid(void); } 55 56 template <typename T> 57 friend T *Cast(FuncObject *func_object); 58 59 private: 60 class Handle { 61 public: ~Handle()62 virtual ~Handle() {} 63 virtual const std::type_info &type() const = 0; 64 virtual Handle *clone() const = 0; 65 }; 66 67 template <typename T> 68 class Object : public Handle { 69 public: 70 Object &operator=(const Object &) = delete; 71 Object(const T & value)72 explicit Object(const T &value) : handle_(value) {} Object(T && value)73 explicit Object(T &&value) : handle_(static_cast<T &&>(value)) {} type()74 const std::type_info &type() const override { return typeid(T); } clone()75 Handle *clone() const override { return new Object(handle_); } 76 T handle_; 77 }; 78 79 Handle *object_{nullptr}; 80 }; 81 82 template <bool, typename T1, typename T2> 83 struct If { 84 using type = T2; 85 }; 86 87 template <typename T1, typename T2> 88 struct If<true, T1, T2> { 89 using type = T1; 90 }; 91 92 template <bool b, typename T1, typename T2> 93 using If_t = typename If<b, T1, T2>::type; 94 95 template <typename T> 96 T *Cast(FuncObject *func_object) { 97 return func_object && func_object->type() == typeid(T) 98 ? &(static_cast<FuncObject::Object<typename std::remove_cv_t<T>> *>(func_object->object_)->handle_) 99 : nullptr; 100 } 101 102 template <typename T> 103 // cppcheck-suppress * 104 T FuncCast(FuncObject &func_object) { 105 using object_type = typename std::remove_reference_t<T>; 106 object_type *result = Cast<object_type>(&func_object); 107 if (!result) { 108 MS_LOG(EXCEPTION) << "Can not convert from " << func_object.type().name() << " to " << typeid(T).name(); 109 } 110 using ref_type = If_t<std::is_reference_v<T>, T, std::add_lvalue_reference_t<T>>; 111 return static_cast<ref_type>(*result); 112 } 113 114 } // namespace mindspore::runtime 115