Home > Back-end >  How to replace #include <optional>
How to replace #include <optional>

Time:09-14

I come to you today with another question that my brain can't process by itself: I got a cpp file that includes optional as a header file. Unfortunately, this works only on c 17 forwards, and I'm trying to compile it in c 14. This cpp file uses optional like this

std::optional<std::string> GetStringPropertyValueFromJson(const std::string& Property, const web::json::value& Json)
{
    if (Json.has_field(utility::conversions::to_string_t(Property)))
    {
        auto& propertyValue = Json.at(utility::conversions::to_string_t(Property));
        if (propertyValue.is_string())
        {
            return std::optional<std::string>{utility::conversions::to_utf8string(propertyValue.as_string())};
        }
    }

    return std::nullopt;
}

and then the function is used to assign values like this:

std::string tokenType = GetStringPropertyValueFromJson("token_type", responseContent).value_or("");
std::string accessToken = GetStringPropertyValueFromJson("access_token", responseContent).value_or("");

Please help me with a proper substitution for OPTIONAL. Thanks and much love

PS: From what i've read, you can replace optional with pair somehow in order to get a similar result, but I don't really know how exactly.

PPS: I am new here so any tips on how to better write my questions or anything else are greatly appreciated :)

CodePudding user response:

I guess in C 14 the optional header could be included by #include <experimental/optional>.

CodePudding user response:

Change your method signature to

std::string GetStringPropertyValueFromJson(const std::string& Property, const web::json::value& Json)

and in the end just return the empty string

return "";

Then later in your code use it without std::optional::value_or:

std::string tokenType = GetStringPropertyValueFromJson("token_type", responseContent);

The logic is exactly the same and you don't use std::optional.

I see now your other question about possibility to use std::pair. Yes, you could also change your method to:

std::pair<std::string, bool> GetStringPropertyValueFromJson(const std::string& Property, const web::json::value& Json)

and return std::make_pair(valueFromJson, true) in case your json property has been found, or std::make_pair("", false) in case it was not. This also solves the problem with empty (but existing) json property.

CodePudding user response:

A poor mans optional string that should be sufficient for your code is this:

struct my_nullopt {};


struct my_optional {
private:
     std::string value; 
     bool has_value = false;
public:
     my_optional(my_nullopt) {} 
     my_optional(const std::string& v) : value(v),has_value(true) {}
     T value_or(const std::string& v) { 
        return has_value ? value : v;
     }
};

Its a rather limited interface, for example it is not possible to set the value after construction. But it appears that you do not need that.

Alternatively you can use boost/optional.

Note that the tip you got about using a pair is just what I did above: The value and a bool. Just that std::pair is for cases where you cannot give better names than first and second (eg in generic code), but it is simple to provide a better interface than std::pair does here. With a pair the value_or would be something along the line of x.first ? x.second : "".


PS: Only in the end I realized that the code you present does not actually make use of what std::optional has to offer. As you are calling value_or(""), you cannot distinguish between a field with value "" or "" because the optional had no value. Because of that, the most simple solution is to use a plain std::string and return "" instead of std::nullopt.

  • Related