aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-04-11 09:20:49 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-04-11 09:20:49 +0200
commit9da5febf1d9af9f5cb62d5d35fc87136e6e4cd60 (patch)
tree6a8d1f857810787cb6e25e6b416ac8bd5eb8b3d7
parent0342dc2fcdd78ef28a4e59d84193a3807068d726 (diff)
Add basic support for variable value inheritance
Currently, only abs_dir_path inherits from dir_path.
-rw-r--r--build2/variable10
-rw-r--r--build2/variable.cxx13
-rw-r--r--build2/variable.ixx16
-rw-r--r--build2/variable.txx2
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>>,