diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-12-01 14:46:45 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-12-01 14:46:45 +0200 |
commit | 10fd2aface4486fc7f873dd2b54a1c2073c0b434 (patch) | |
tree | 5133810cf33b3e4ba4dfe78f659ee65599c31ffd /build/target-type | |
parent | 7996c2bfc2d7e998e2f9f1236d457ec7bea8ad8a (diff) |
Reimplement define as dynamic derivation rather than alias
New syntax:
define cli: file
The rationale is we need to be able to assign the file extension (using
type/pattern-specific variables). And if it is an alias, we will assign
it to the original target type.
Note that we could still support aliases if we need to. Will need to
bring back the id member in target_type that would normally point to
itself but for an alias would point to the origin.
Diffstat (limited to 'build/target-type')
-rw-r--r-- | build/target-type | 57 |
1 files changed, 24 insertions, 33 deletions
diff --git a/build/target-type b/build/target-type index 2c93455..e299fe2 100644 --- a/build/target-type +++ b/build/target-type @@ -8,9 +8,6 @@ #include <map> #include <string> #include <ostream> -#include <typeindex> - -#include <butl/utility> // compare_c_string #include <build/types> @@ -23,9 +20,13 @@ namespace build // Target type. // + // Note that we assume there is always a single instance of this class + // for any target type. As a result, we can use address comparison to + // determine if two target types are the same. + // + // struct target_type { - std::type_index id; const char* name; const target_type* base; target* (*factory) (const target_type&, dir_path, string, const string*); @@ -33,60 +34,50 @@ namespace build target* (*search) (const prerequisite_key&); bool see_through; // A group with the default "see through" semantics. - const target_type* origin; // Original target if this is an alias. - bool - is_a (const std::type_index&) const; // Defined in target.cxx + is_a (const target_type&) const; // Defined in target.cxx template <typename T> bool - is_a () const {return is_a (typeid (T));} + is_a () const {return is_a (T::static_type);} }; inline bool - operator< (const target_type& x, const target_type& y) - { - return x.id < y.id; - } + operator< (const target_type& x, const target_type& y) {return &x < &y;} + + inline bool + operator== (const target_type& x, const target_type& y) {return &x == &y;} + + inline bool + operator!= (const target_type& x, const target_type& y) {return &x != &y;} inline std::ostream& - operator<< (std::ostream& os, const target_type& tt) - { - return os << tt.name; - } + operator<< (std::ostream& os, const target_type& tt) {return os << tt.name;} // Target type map. // struct target_type_ref { - // Like reference_wrapper except it deletes the target type if it is - // an alias (aliases are always dynamically allocated). + // Like reference_wrapper except it sometimes deletes the target type. // explicit - target_type_ref (const target_type& r): p_ (&r) - { - assert (p_->origin == nullptr); - } + target_type_ref (const target_type& r): p_ (&r), d_ (false) {} explicit - target_type_ref (unique_ptr<target_type>&& p): p_ (p.release ()) - { - assert (p_->origin != nullptr); - } + target_type_ref (unique_ptr<target_type>&& p) + : p_ (p.release ()), d_ (true) {} + + target_type_ref (target_type_ref&& r) + : p_ (r.p_), d_ (r.d_) {r.p_ = nullptr;} - ~target_type_ref () - { - if (p_ != nullptr && p_->origin != nullptr) - delete p_; - } + ~target_type_ref () {if (p_ != nullptr && d_) delete p_;} explicit operator const target_type& () const {return *p_;} const target_type& get () const {return *p_;} - target_type_ref (target_type_ref&& r): p_ (r.p_) {r.p_ = nullptr;} - private: const target_type* p_; + bool d_; }; using target_type_map_base = std::map<string, target_type_ref>; |