From 9da5febf1d9af9f5cb62d5d35fc87136e6e4cd60 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 11 Apr 2016 09:20:49 +0200 Subject: Add basic support for variable value inheritance Currently, only abs_dir_path inherits from dir_path. --- build2/variable | 10 +++++++++- build2/variable.cxx | 13 ++++++++++--- build2/variable.ixx | 16 +++++++++++++--- build2/variable.txx | 2 ++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/build2/variable b/build2/variable index 14bf7af..ebf0f02 100644 --- a/build2/variable +++ b/build2/variable @@ -28,6 +28,14 @@ namespace build2 const char* name; // Type name for diagnostics. const size_t size; // Type size in value::data_ (only used for PODs). + // Base type, if any. We have very limited support for inheritance: a + // const value (but not non-const) can be cast to the base type. In + // particular, a derived/base value cannot be assigned to base/derived. + // If not NULL, then the cast function below is expected to return the + // base pointer if its second argument points to the base's value_type. + // + const value_type* base; + // Destroy the value. If it is NULL, then the type is assumed to be POD // with a trivial destructor. // @@ -59,7 +67,7 @@ namespace build2 // static_cast to const T*. If it is NULL, then cast data_ directly. Note // that this function is used for both const and non-const values. // - const void* (*const cast) (const value&); + const void* (*const cast) (const value&, const value_type*); // If NULL, then the types are compared as PODs using memcmp(). // diff --git a/build2/variable.cxx b/build2/variable.cxx index db65e5b..c4e2721 100644 --- a/build2/variable.cxx +++ b/build2/variable.cxx @@ -313,6 +313,7 @@ namespace build2 { "bool", sizeof (bool), + nullptr, // No base. nullptr, // No dtor (POD). nullptr, // No copy_ctor (POD). nullptr, // No copy_assign (POD). @@ -350,6 +351,7 @@ namespace build2 { "uint64", sizeof (uint64_t), + nullptr, // No base. nullptr, // No dtor (POD). nullptr, // No copy_ctor (POD). nullptr, // No copy_assign (POD). @@ -433,6 +435,7 @@ namespace build2 { "string", sizeof (string), + nullptr, // No base. &default_dtor, &default_copy_ctor, &default_copy_assign, @@ -475,6 +478,7 @@ namespace build2 { "path", sizeof (path), + nullptr, // No base. &default_dtor, &default_copy_ctor, &default_copy_assign, @@ -515,6 +519,7 @@ namespace build2 { "dir_path", sizeof (dir_path), + nullptr, // No base, or should it be path? &default_dtor, &default_copy_ctor, &default_copy_assign, @@ -545,14 +550,15 @@ namespace build2 { "abs_dir_path", sizeof (abs_dir_path), + &value_traits::value_type, // Assume direct cast works for both. &default_dtor, &default_copy_ctor, &default_copy_assign, - &simple_assign, // Allow empty paths. + &simple_assign, // Allow empty paths. &simple_append, - nullptr, // No prepend. + nullptr, // No prepend. &simple_reverse, - nullptr, // No cast (cast data_ directly). + nullptr, // No cast (cast data_ directly). &simple_compare }; @@ -577,6 +583,7 @@ namespace build2 { "name", sizeof (name), + nullptr, // No base. &default_dtor, &default_copy_ctor, &default_copy_assign, diff --git a/build2/variable.ixx b/build2/variable.ixx index e52a150..9b29608 100644 --- a/build2/variable.ixx +++ b/build2/variable.ixx @@ -81,17 +81,27 @@ namespace build2 inline const T& cast (const value& v) { - assert (!v.null () && v.type == &value_traits::value_type); + assert (!v.null ()); + + // Find base if any. + // + const value_type* b (v.type); + for (; b != nullptr && b != &value_traits::value_type; b = b->base) ; + assert (b != nullptr); + return *static_cast (v.type->cast == nullptr ? static_cast (&v.data_) - : v.type->cast (v)); + : v.type->cast (v, b)); } template inline T& cast (value& v) { - return const_cast (cast (static_cast (v))); + assert (!v.null () && v.type == &value_traits::value_type); + return *static_cast (v.type->cast == nullptr + ? static_cast (&v.data_) + : const_cast (v.type->cast (v, v.type))); } template diff --git a/build2/variable.txx b/build2/variable.txx index bd7a18b..99ea79b 100644 --- a/build2/variable.txx +++ b/build2/variable.txx @@ -254,6 +254,7 @@ namespace build2 { value_traits>::type_name.c_str (), sizeof (vector), + nullptr, // No base. &default_dtor>, &default_copy_ctor>, &default_copy_assign>, @@ -392,6 +393,7 @@ namespace build2 { value_traits>::type_name.c_str (), sizeof (map), + nullptr, // No base. &default_dtor>, &default_copy_ctor>, &default_copy_assign>, -- cgit v1.1