forked from huawei/mindspore2022
219 lines
5.8 KiB
C++
219 lines
5.8 KiB
C++
/**
|
|
* Copyright 2019 Huawei Technologies Co., Ltd
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifndef MINDSPORE_CCSRC_UTILS_ANY_H_
|
|
#define MINDSPORE_CCSRC_UTILS_ANY_H_
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <typeinfo>
|
|
#include <typeindex>
|
|
#include <memory>
|
|
#include <functional>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <utility>
|
|
|
|
#include "pybind11/pybind11.h"
|
|
|
|
#include "utils/overload.h"
|
|
#include "utils/log_adapter.h"
|
|
#include "utils/misc.h"
|
|
|
|
namespace mindspore {
|
|
// usage:AnyPtr sp = std::make_shared<Any>(aname);
|
|
template <class T>
|
|
std::string type(const T& t) {
|
|
return demangle(typeid(t).name());
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& os, const pybind11::object& obj);
|
|
|
|
class Any {
|
|
public:
|
|
// constructors
|
|
Any() : m_ptr(nullptr), m_tpIndex(std::type_index(typeid(void))) {}
|
|
Any(const Any& other) : m_ptr(other.clone()), m_tpIndex(other.m_tpIndex) {}
|
|
Any(Any&& other) : m_ptr(std::move(other.m_ptr)), m_tpIndex(std::move(other.m_tpIndex)) {}
|
|
|
|
Any& operator=(Any&& other);
|
|
// right reference constructor
|
|
template <class T, class = typename std::enable_if<!std::is_same<typename std::decay<T>::type, Any>::value, T>::type>
|
|
Any(T&& t) : m_tpIndex(typeid(typename std::decay<T>::type)) { // NOLINT
|
|
BasePtr new_val(new Derived<typename std::decay<T>::type>(std::forward<T>(t)));
|
|
std::swap(m_ptr, new_val);
|
|
}
|
|
|
|
~Any() = default;
|
|
|
|
// judge whether is empty
|
|
bool empty() const { return m_ptr == nullptr; }
|
|
|
|
// judge the is relation
|
|
template <class T>
|
|
bool is() const {
|
|
return m_tpIndex == std::type_index(typeid(T));
|
|
}
|
|
|
|
const std::type_info& type() const { return m_ptr ? m_ptr->type() : typeid(void); }
|
|
|
|
std::size_t Hash() const {
|
|
std::stringstream buffer;
|
|
buffer << m_tpIndex.name();
|
|
if (m_ptr != nullptr) {
|
|
buffer << m_ptr->GetString();
|
|
}
|
|
return std::hash<std::string>()(buffer.str());
|
|
}
|
|
|
|
template <typename T>
|
|
bool Apply(const std::function<void(T&)>& fn) {
|
|
if (type() == typeid(T)) {
|
|
T x = cast<T>();
|
|
fn(x);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string GetString() const {
|
|
if (m_ptr != nullptr) {
|
|
return m_ptr->GetString();
|
|
} else {
|
|
return std::string("");
|
|
}
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const Any& any) {
|
|
os << any.GetString();
|
|
return os;
|
|
}
|
|
|
|
// type cast
|
|
template <class T>
|
|
T& cast() const {
|
|
if (!is<T>() || !m_ptr) {
|
|
// Use MS_LOGFATAL replace throw std::bad_cast()
|
|
MS_LOG(EXCEPTION) << "can not cast " << m_tpIndex.name() << " to " << typeid(T).name();
|
|
}
|
|
auto ptr = static_cast<Derived<T>*>(m_ptr.get());
|
|
return ptr->m_value;
|
|
}
|
|
|
|
bool operator==(const Any& other) const {
|
|
if (m_tpIndex != other.m_tpIndex) {
|
|
return false;
|
|
}
|
|
if (m_ptr == nullptr && other.m_ptr == nullptr) {
|
|
return true;
|
|
}
|
|
if (m_ptr == nullptr || other.m_ptr == nullptr) {
|
|
return false;
|
|
}
|
|
return *m_ptr == *other.m_ptr;
|
|
}
|
|
|
|
bool operator!=(const Any& other) const { return !(operator==(other)); }
|
|
|
|
Any& operator=(const Any& other);
|
|
|
|
bool operator<(const Any& other) const;
|
|
|
|
std::string ToString() const {
|
|
std::ostringstream buffer;
|
|
if (m_tpIndex == typeid(float)) {
|
|
buffer << "<float> " << cast<float>();
|
|
} else if (m_tpIndex == typeid(double)) {
|
|
buffer << "<double> " << cast<double>();
|
|
} else if (m_tpIndex == typeid(int)) {
|
|
buffer << "<int> " << cast<int>();
|
|
} else if (m_tpIndex == typeid(bool)) {
|
|
buffer << "<bool> " << cast<bool>();
|
|
} else {
|
|
buffer << "<" << demangle(m_tpIndex.name()) << "> " << m_ptr->GetString();
|
|
}
|
|
return buffer.str();
|
|
}
|
|
__attribute__((used)) void dump() const { std::cout << ToString() << std::endl; }
|
|
|
|
private:
|
|
struct Base;
|
|
using BasePtr = std::unique_ptr<Base>;
|
|
|
|
// type base definition
|
|
struct Base {
|
|
virtual const std::type_info& type() const = 0;
|
|
virtual BasePtr clone() const = 0;
|
|
virtual ~Base() = default;
|
|
virtual bool operator==(const Base& other) const = 0;
|
|
virtual std::string GetString() = 0;
|
|
};
|
|
|
|
template <typename T>
|
|
struct Derived : public Base {
|
|
template <typename... Args>
|
|
explicit Derived(Args&&... args) : m_value(std::forward<Args>(args)...), serialize_cache_("") {}
|
|
|
|
bool operator==(const Base& other) const override {
|
|
if (typeid(*this) != typeid(other)) {
|
|
return false;
|
|
}
|
|
return m_value == static_cast<const Derived<T>&>(other).m_value;
|
|
}
|
|
|
|
const std::type_info& type() const override { return typeid(T); }
|
|
|
|
BasePtr clone() const override { return BasePtr(new Derived<T>(m_value)); }
|
|
|
|
~Derived() override {}
|
|
|
|
std::string GetString() override {
|
|
std::stringstream buffer;
|
|
buffer << m_value;
|
|
return buffer.str();
|
|
}
|
|
|
|
T m_value;
|
|
std::string serialize_cache_;
|
|
};
|
|
|
|
// clone method
|
|
BasePtr clone() const {
|
|
if (m_ptr != nullptr) {
|
|
return m_ptr->clone();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
BasePtr m_ptr; // point to real data
|
|
std::type_index m_tpIndex; // type info of data
|
|
};
|
|
|
|
using AnyPtr = std::shared_ptr<Any>;
|
|
|
|
struct AnyHash {
|
|
std::size_t operator()(const Any& c) const { return c.Hash(); }
|
|
};
|
|
|
|
struct AnyLess {
|
|
bool operator()(const Any& a, const Any& b) const { return a.Hash() < b.Hash(); }
|
|
};
|
|
|
|
bool AnyIsLiteral(const Any& any);
|
|
|
|
} // namespace mindspore
|
|
|
|
#endif // MINDSPORE_CCSRC_UTILS_ANY_H_
|