3

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!

Ronald joe
  • 339
  • 2
  • 9
  • Your title is a bit misleading. These are language features that affect API, not any under-the-hood stuff. As it is, the title makes it sound like you'd ask something like how it can construct and destroy in-place to switch between engaged and disengaged. – chris Aug 30 '20 at 19:15
  • @chris I'm not 100 % sure what you're trying to say... but what do you suggest ? – Ronald joe Aug 30 '20 at 19:17
  • Well, there are actually two questions in there. One is about using `{}` in place of an `optional` object and one is about an optional object acting like a `bool`. It's difficult to find a specific title that encompasses both questions. Each individually is pretty straightforward ("How do I enable my class to use {} in place of an object?", "How do I make my class act like a bool?") – chris Aug 30 '20 at 19:18
  • 2
    `return {}` here says "return an instance of `std::optional`, initialized with the default constructor". It's a shorthand for `return std::optional();`. This syntax is not specific to `std::optional`. It so happens that the default constructor of `std::optional` sets up the object in the empty state. – Igor Tandetnik Aug 30 '20 at 19:20
  • 1
    `if(name)` here is equivalent to `if (name.operator bool())` - it calls [a conversion operator](https://en.cppreference.com/w/cpp/utility/optional/operator_bool) that `std::optional` provides. This operator does the same thing as `has_value()` – Igor Tandetnik Aug 30 '20 at 19:23
  • These answers didn't answer what I wanted, but this was helpful: https://stackoverflow.com/questions/16860960/how-should-one-use-stdoptional – Andrew Sep 11 '20 at 02:14

2 Answers2

0
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.

super
  • 12,335
  • 2
  • 19
  • 29
  • 1
    The biggest difference between this example and actual `std::optional` implementation is that yours constructs an instance of `T` even when it supposedly doesn't have a value. The real `std::optional` won't. – Igor Tandetnik Aug 30 '20 at 19:26
  • 1
    `std::optional` uses `explicit operator bool`. The conversion is *explicit*, not implicit. – Konrad Rudolph Aug 30 '20 at 19:27
0

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.

eerorika
  • 232,697
  • 12
  • 197
  • 326