#pragma once #include #include #include #include class Type; class Value; class User; struct Use; class Value { public: Value(const Value& other) = delete; Value(Value&& other) noexcept = delete; Value& operator=(const Value& other) = delete; Value& operator=(Value&& other) noexcept = delete; explicit Value(Type *ty, std::string name = "") : type_(ty), name_(std::move(name)){} virtual ~Value(); std::string get_name() const { return name_; } Type *get_type() const { return type_; } const std::list &get_use_list() const { return use_list_; } bool set_name(const std::string& name); void add_use(User *user, unsigned arg_no); void remove_use(User *user, unsigned arg_no); void replace_all_use_with(Value *new_val) const; void replace_use_with_if(Value *new_val, const std::function& should_replace); virtual std::string print() = 0; template T *as() { static_assert(std::is_base_of_v, "T must be a subclass of Value"); const auto ptr = dynamic_cast(this); assert(ptr && "dynamic_cast failed"); return ptr; } template const T* as() const { static_assert(std::is_base_of_v, "T must be a subclass of Value"); const auto ptr = dynamic_cast(this); assert(ptr); return ptr; } // is 接口 template bool is() const { static_assert(std::is_base_of_v, "T must be a subclass of Value"); return dynamic_cast(this); } private: Type *type_; std::list use_list_; // who use this value std::string name_; // should we put name field here ? };