c++ - Efficient Value type -


i want create efficient , easy use value type. base of value boost::variant (and std::variant in future), i'm new in it. , have questions:

  • in code below, necessary use recursive variant?
  • is possible not inherit boost::variant? maybe more efficient way exists?
  • do have comments or suggestions on code below (it's not completed code, draft)?
     class value;      typedef std::string                 string;     typedef std::vector<char>           bindata;     typedef string                      url;     typedef unsigned long long          uid;     tsw_strong_typedef(std::time_t, time)      typedef std::vector<value>          valuearray;     typedef std::vector<string>         stringarray;     //typedef std::pair<string, value>    namevalue;      typedef std::list<value>            valuelist;     typedef std::list<string>           stringlist;     typedef std::map<string, string>    stringstringmap;     typedef std::map<string, value>     namevaluemap;      struct monostate     {         monostate() = default;     };      constexpr bool operator<(monostate, monostate) noexcept { return false; }     constexpr bool operator>(monostate, monostate) noexcept { return false; }     constexpr bool operator<=(monostate, monostate) noexcept { return true; }     constexpr bool operator>=(monostate, monostate) noexcept { return true; }     constexpr bool operator==(monostate, monostate) noexcept { return true; }     constexpr bool operator!=(monostate, monostate) noexcept { return false; }       typedef monostate null;       class object     {     public:         object() = delete;         object(const object &other) = default;         object(object &&other);          object(const string &name);         object(string &&name);         object(const string &name, const namevaluemap &fields);         object(string &&name, const namevaluemap &fields);         object(const string &name, namevaluemap &&fields);         object(string &&name, namevaluemap &&fields);          object &operator=(const object &other) = default;         object &operator=(object &&other);      public:         const string &get_name() const;         const namevaluemap &get_fields() const;      public:         bool operator<(const object &other) const noexcept;         bool operator>(const object &other) const noexcept;         bool operator<=(const object &other) const noexcept;         bool operator>=(const object &other) const noexcept;         bool operator==(const object &other) const noexcept;         bool operator!=(const object &other) const noexcept;      private:         string name_;         namevaluemap fields_;     };       enum class valuetype     {         undefined, null, array, bindata, boolean, doublenumber, int64number, string, time, object     };      // types ordnung need same valuetype ordnung.     /// base value class     typedef boost::variant<monostate, null, valuearray, bindata, bool, double, int64_t, string, time, object> valuebase;       /**     * @brief value class, implements common framework value.     *     * class container, can store multiple values, including values containers.     *     * @note     * class based on variant class. may either boost::variant or std::variant in c++17 , higher.     */     class value : public valuebase     {     public:         using valuebase::valuebase;         value() = default;         value(const string::value_type *v) : valuebase(string(v)) {}      public:         bool is_array() const { return static_cast<valuetype>(which()) == valuetype::array; }         bool is_bool() const { return static_cast<valuetype>(which()) == valuetype::boolean; }         bool is_bindata() const { return static_cast<valuetype>(which()) == valuetype::bindata; }         bool is_double() const { return static_cast<valuetype>(which()) == valuetype::doublenumber; }         bool is_int64() const { return static_cast<valuetype>(which()) == valuetype::int64number; }         bool is_null() const { return static_cast<valuetype>(which()) == valuetype::null; }         bool is_object() const { return static_cast<valuetype>(which()) == valuetype::object; }         bool is_string() const { return static_cast<valuetype>(which()) == valuetype::string; }         bool is_time() const { return static_cast<valuetype>(which()) == valuetype::time; }         bool is_undefined() const { return static_cast<valuetype>(which()) == valuetype::undefined; }      public:         bool          as_bool() const  { return as<bool>(); }         bindata       &as_bindata()  { return as<bindata>(); }         double        as_double() const  { return as<double>(); }         int64_t       as_int64() const  { return as<int64_t>(); }         object        &as_object()  { return as<object>(); }         string        &as_string()  { return as<string>(); }         time          &as_time()  { return as<time>(); }         valuearray    &as_array()  { return as<valuearray>(); }      public:         valuetype     value_type() const  { return static_cast<valuetype>(which()); }      public:         template <typename t>         const t& as() const { return boost::get<t>(*this); }          template <typename t>         t& as() { return boost::get<t>(*this); }          template <typename t>         const t& as(const t& default_value) const { return type() == typeid(t) ? boost::get<t>(*this) : default_value; }          template <typename t>         t& as(const t& default_value) { return type() == typeid(t) ? boost::get<t>(*this) : default_value; }          template <typename t> boost::optional<t> as_optional() { return boost::make_optional(type() == typeid(t), as<t>()); }      public:         bool operator==(const valuebase &other) const { return valuebase::operator==(other); }         bool operator<(const valuebase &other) const { return valuebase::operator<(other); }         bool operator>(const valuebase &other) const { return !((*this) < other || (*this) == other); }         bool operator<=(const valuebase &other) const { return ((*this) < other || (*this) == other); }         bool operator>=(const valuebase &other) const { return !((*this) < other); }         bool operator!=(const valuebase &other) const { return !((*this) == other); }      private:         // force compile error, prevent variant(bool) called         value(void *) = delete;     }; 

looks okay me.

you can without recursive variants iff standard library implementation allows instantiation of container classes incomplete types.

i'd note since tied base-class publicly, there nothing implementation can change without changing (binary) interface. therefore i'd surely implement members inline compiler optimize them without lto.

it not clear me to_x members (possibly a<x> possibly else depending on can_convert()?). if it's wrap around as_<> i'd rename them as_x() etc.

you might want add optional<>-like members like

template <typename t> t const& get_value_or(t const& default_value) const; 

and possibly

template <typename t> optional<t> get() const; // boost optional can prevent copy²: template <typename t> optional<t const&> get() const; 

this enables code like:

if (auto& s = value.get<string>()) {      std::cout << "the string value '" << *s << "'\n"; } else {      std::cout << "value has no string value\n"; } 

¹ not - yet - standard specified. can use boost container instead promises this, non-allocating construction

² make sure not allow operation on rvalue, remove predictable class of errors, e.g.

template <typename t> optional<t const&> get()&& = delete; 

Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -