Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Templated value checking and getter #316

Closed
miloyip opened this issue Apr 24, 2015 · 1 comment
Closed

Templated value checking and getter #316

miloyip opened this issue Apr 24, 2015 · 1 comment
Milestone

Comments

@miloyip
Copy link
Collaborator

miloyip commented Apr 24, 2015

Provide templated functions:

bool Value::Is<int>() const;
int Value::Get<int>() const;
...

These functions are useful when the user code has templated types.

A difficulty is that current RapidJSON does not provide adapter classes for array and object. As @pah suggested in #162 (comment), we can add some class like that. So we can also have Array Value::GetArray() and Array Get<Array>(), etc.

I create this issue for replacing #153.

@miloyip miloyip added this to the v1.1 Beta milestone Apr 24, 2015
@zarlin
Copy link

zarlin commented Dec 4, 2015

I was missing the templated Is and Get functions as well, so I wrote an implementation. Right now it only supports the 'value' types (bool, numbers and string). I saw another issue that requested float overloads as well, so those are included. The floats are also useful for the special Get function on the bottom of this post.

Is

    //template functions for determining if value is of a type
    template<typename Other> bool Is() const    { static_assert(false, "Type not supported"); }
    template<> bool Is<bool>() const            { return IsBool(); }
    template<> bool Is<int32_t>() const         { return IsInt(); }
    template<> bool Is<int64_t>() const         { return IsInt64(); }
    template<> bool Is<uint32_t>() const        { return IsUint(); }
    template<> bool Is<uint64_t>() const        { return IsUint64(); }
    template<> bool Is<float>() const           { return IsDouble(); }
    template<> bool Is<double>() const          { return IsDouble(); }
#if RAPIDJSON_HAS_STDSTRING
    template<> bool Is<std::string>() const     { return IsString(); }
#else
    template<> bool Is<char*>() const           { return IsString(); }
#endif

Get

    //template functions for obtainign the value as a type
    template<typename Other> Other Get() const  { static_assert(false, "Type not supported"); }
    template<> bool Get<bool>() const           { return GetBool(); }
    template<> int32_t Get<int32_t>() const     { return GetInt(); }
    template<> uint32_t Get<uint32_t>() const   { return GetUint(); }
    template<> int64_t Get<int64_t>() const     { return GetInt64(); }
    template<> uint64_t Get<uint64_t>() const   { return GetUint64(); }
    template<> float Get<float>() const         { return GetDouble(); }
    template<> double Get<double>() const       { return GetDouble(); }
#if RAPIDJSON_HAS_STDSTRING
    template<> std::string Get<std::string>() const { return GetString(); }
#else
    template<> char* Get<char*>() const         { return GetString(); }
#endif

Below is an additional Get function that passes a reference to the target variable the result should be stored in. The type is deduced from the passed target. A bool is returned to indicate success or failure. This is mostly a shortcut, but allows making very clean parsing code.

    //function that tries to obtain a value with the given name
    template <typename Target>
    bool Get(const char* name, Target& target) const
    {
        ConstMemberIterator& v = FindMember(name);
        if (v != MemberEnd() && v->value.Is<Target>())
        {
            target = v->value.Get<Target>();
            return true;
        }
        return false;
    }

example usage

    int foo;
    if (!value.Get("foo", foo))
        foo = 1;//default/fallback value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants