From b86c1d8d2e0be140f6854d869e07139ff3c4221c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 24 Aug 2020 10:51:26 +0200 Subject: Add copying version of convert(value) --- libbuild2/variable.cxx | 18 ++++++++++++++++++ libbuild2/variable.hxx | 6 ++++++ libbuild2/variable.ixx | 18 ++++++++++++++---- libbuild2/variable.txx | 22 ++++++++++++++-------- 4 files changed, 52 insertions(+), 12 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx index a4c3ef3..91b25bd 100644 --- a/libbuild2/variable.cxx +++ b/libbuild2/variable.cxx @@ -410,6 +410,24 @@ namespace build2 v.assign (move (ns), nullptr); // Assign new data. } + [[noreturn]] void + convert_throw (const value_type* from, const value_type& to) + { + string m ("invalid "); + m += to.name; + m += " value: "; + + if (from != nullptr) + { + m += "conversion from "; + m += from->name; + } + else + m += "null"; + + throw invalid_argument (move (m)); + } + // Throw invalid_argument for an invalid simple value. // [[noreturn]] static void diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx index 6c78c95..3152c71 100644 --- a/libbuild2/variable.hxx +++ b/libbuild2/variable.hxx @@ -47,6 +47,8 @@ namespace build2 // const value_type* base_type; + template const value_type* is_a () const; + // Element type, if this is a vector. // const value_type* element_type; @@ -628,6 +630,10 @@ namespace build2 // template T convert (value&&); + // As above but preserving the value. + // + template T convert (const value&); + // Default implementations of the dtor/copy_ctor/copy_assing callbacks for // types that are stored directly in value::data_ and the provide all the // necessary functions (copy/move ctor and assignment operator). diff --git a/libbuild2/variable.ixx b/libbuild2/variable.ixx index a11ee12..c8f9541 100644 --- a/libbuild2/variable.ixx +++ b/libbuild2/variable.ixx @@ -7,6 +7,19 @@ namespace build2 { + // value_type + // + template + inline const value_type* value_type:: + is_a () const + { + const value_type* b (this); + for (; + b != nullptr && b != &value_traits::value_type; + b = b->base_type) ; + return b; + } + // value // inline bool value:: @@ -169,10 +182,7 @@ namespace build2 // // Note that here we use the value type address as type identity. // - const value_type* b (v.type); - for (; - b != nullptr && b != &value_traits::value_type; - b = b->base_type) ; + const value_type* b (v.type->is_a ()); assert (b != nullptr); return *static_cast (v.type->cast == nullptr diff --git a/libbuild2/variable.txx b/libbuild2/variable.txx index 51176ae..0e10e87 100644 --- a/libbuild2/variable.txx +++ b/libbuild2/variable.txx @@ -55,6 +55,9 @@ namespace build2 (n == 0 ? " value: empty" : " value: multiple names")); } + [[noreturn]] void + convert_throw (const value_type* from, const value_type& to); + template T convert (value&& v) @@ -67,19 +70,22 @@ namespace build2 return move (v).as (); } - string m ("invalid "); - m += value_traits::value_type.name; - m += " value: "; + convert_throw (v ? v.type : nullptr, value_traits::value_type); + } + template + T + convert (const value& v) + { if (v) { - m += "conversion from "; - m += v.type->name; + if (v.type == nullptr) + return convert (names (v.as ())); + else if (v.type == &value_traits::value_type) + return v.as (); } - else - m += "null"; - throw invalid_argument (move (m)); + convert_throw (v ? v.type : nullptr, value_traits::value_type); } template -- cgit v1.1