diff options
-rw-r--r-- | build2/variable | 10 | ||||
-rw-r--r-- | build2/variable.cxx | 13 | ||||
-rw-r--r-- | build2/variable.ixx | 16 | ||||
-rw-r--r-- | 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<string>, &default_copy_ctor<string>, &default_copy_assign<string>, @@ -475,6 +478,7 @@ namespace build2 { "path", sizeof (path), + nullptr, // No base. &default_dtor<path>, &default_copy_ctor<path>, &default_copy_assign<path>, @@ -515,6 +519,7 @@ namespace build2 { "dir_path", sizeof (dir_path), + nullptr, // No base, or should it be path? &default_dtor<dir_path>, &default_copy_ctor<dir_path>, &default_copy_assign<dir_path>, @@ -545,14 +550,15 @@ namespace build2 { "abs_dir_path", sizeof (abs_dir_path), + &value_traits<dir_path>::value_type, // Assume direct cast works for both. &default_dtor<abs_dir_path>, &default_copy_ctor<abs_dir_path>, &default_copy_assign<abs_dir_path>, - &simple_assign<abs_dir_path, true>, // Allow empty paths. + &simple_assign<abs_dir_path, true>, // Allow empty paths. &simple_append<abs_dir_path, true>, - nullptr, // No prepend. + nullptr, // No prepend. &simple_reverse<abs_dir_path>, - nullptr, // No cast (cast data_ directly). + nullptr, // No cast (cast data_ directly). &simple_compare<abs_dir_path> }; @@ -577,6 +583,7 @@ namespace build2 { "name", sizeof (name), + nullptr, // No base. &default_dtor<name>, &default_copy_ctor<name>, &default_copy_assign<name>, 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<T>::value_type); + assert (!v.null ()); + + // Find base if any. + // + const value_type* b (v.type); + for (; b != nullptr && b != &value_traits<T>::value_type; b = b->base) ; + assert (b != nullptr); + return *static_cast<const T*> (v.type->cast == nullptr ? static_cast<const void*> (&v.data_) - : v.type->cast (v)); + : v.type->cast (v, b)); } template <typename T> inline T& cast (value& v) { - return const_cast<T&> (cast<T> (static_cast<const value&> (v))); + assert (!v.null () && v.type == &value_traits<T>::value_type); + return *static_cast<T*> (v.type->cast == nullptr + ? static_cast<void*> (&v.data_) + : const_cast<void*> (v.type->cast (v, v.type))); } template <typename T> 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<vector<T>>::type_name.c_str (), sizeof (vector<T>), + nullptr, // No base. &default_dtor<vector<T>>, &default_copy_ctor<vector<T>>, &default_copy_assign<vector<T>>, @@ -392,6 +393,7 @@ namespace build2 { value_traits<map<K, V>>::type_name.c_str (), sizeof (map<K, V>), + nullptr, // No base. &default_dtor<map<K, V>>, &default_copy_ctor<map<K, V>>, &default_copy_assign<map<K, V>>, |