From 7996c2bfc2d7e998e2f9f1236d457ec7bea8ad8a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 1 Dec 2015 13:39:09 +0200 Subject: Implement support for definition target type aliases For example: define cli=file Currently, the semantics is that of a real alias with only name differences that are used for display. See tests/define/buildfile for more use cases. --- build/target-type | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'build/target-type') diff --git a/build/target-type b/build/target-type index 154714c..2c93455 100644 --- a/build/target-type +++ b/build/target-type @@ -9,7 +9,6 @@ #include #include #include -#include // reference_wrapper #include // compare_c_string @@ -29,11 +28,13 @@ namespace build std::type_index id; const char* name; const target_type* base; - target* (*const factory) (dir_path, std::string, const std::string*); - const std::string& (*const extension) (const target_key&, scope&); - target* (*const search) (const prerequisite_key&); + target* (*factory) (const target_type&, dir_path, string, const string*); + const string& (*extension) (const target_key&, scope&); + 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 @@ -56,16 +57,45 @@ namespace build // Target type map. // - using target_type_map_base = std::map< - const char*, - std::reference_wrapper, - butl::compare_c_string>; + struct target_type_ref + { + // Like reference_wrapper except it deletes the target type if it is + // an alias (aliases are always dynamically allocated). + // + explicit + target_type_ref (const target_type& r): p_ (&r) + { + assert (p_->origin == nullptr); + } + + explicit + target_type_ref (unique_ptr&& p): p_ (p.release ()) + { + assert (p_->origin != nullptr); + } + + ~target_type_ref () + { + if (p_ != nullptr && p_->origin != nullptr) + 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_; + }; + + using target_type_map_base = std::map; class target_type_map: public target_type_map_base { public: void - insert (const target_type& tt) {emplace (tt.name, tt);} + insert (const target_type& tt) {emplace (tt.name, target_type_ref (tt));} template void -- cgit v1.1