how does std::optional work under the hood?

Viewed 375

I just learned about the std::optional feature in c++ 17 along with a few other very useful features...

but there is a few things that I don't understand about std::optional that I would like someone to explain them to me:

first of all as far as I know in std::optional the return value can either be the specified type or it can be nothing like this :

std::optional<std::string> getName()
{
    if(person.hasName())
    {
        return person.name;
    }
    else 
    {
        return {};
    }
}

how does return {} returns nothing ? like for example if I was to make a similar class that return either the specified value or nothing, how do I make my own class so return {} is valid ? I'm I misunderstanding something here ?

my second question is that when you want to check the return value you can either do :

int main()
{
    std::optional<std::string> name = getName();
    if(name.has_value())  // check if the name is valid using the has_value function
    {
        ...
    }
}

or i can also do :


int main()
{
    std::optional<std::string> name = getName();
    if(name)  // check if the name is valid only using the variable name ???
    {
        ...
    }
}

I'm really confused about this how could a variable name return a boolean ? not like the constructor of an object can return anything, so how is this possible ?

again let's say I want to make my own class that is kind of similar to std::optional how do I make it so an instance of my class can be used as a boolean ?

I would really appreciate answers that adress my questions and not something related to when to use std::optional or why I shouldn't make my own class that does the same thing etc...

thanks!

2 Answers
return {};

will simply call the default constructor of the class.

By giving the class a conversion operator to bool it can be implicitly converted to a bool when needed.

It would look something along the lines of

template <typename T>
class optional {
    public:
    optional() {}
    optional(T t) : has_value(true), value(std::move(t)) {}

    operator bool() {
        return has_value;
    }
    
    private:
    bool has_value = false;
    T value;
}

Very simplified, missing assignement operators and more.

how do I make my own class so return {} is valid ?

By making the class default constructible. Exactly how to do that depends on the class. In cases where the class is implicitly default constructible you need to do nothing, while in other cases you may need to explicitly declare the constructor. Like this for example: ClassName() = default;.

how could a variable name return a boolean

Think about how this variable name "returns a boolean":

int x = 42;
if (x)
    ;

Or how this variable name "returns a std::string_view":

const char* str = "example";
std::string__view sv = str;

This is called a conversion from one type to another. That is what happens in if(name).

how do I make it so an instance of my class can be used as a boolean ?

By providing a conversion operator.

Related