2

I put std::optional in the constructor of a class. But when I make an instance of that class, leaving out the optional argument, I get the error that no such constructor exists for that class. I would like to know how to properly use std::optional.

The constructor for my class 'Car' looks like this:

Car::Car(string make, string model, Racer *driver, optional<Racer*> codriver) : m_make(make), m_model(model), m_driver(driver), m_codriver(codriver)
{
}

This is what my main looks like:

void main()
{
    Racer *r1 = new Racer{ "John Doe", "male", "08/05/1987", "Ford" };
    Racer *r2 = new Racer{ "Jane Doe", "male", "06/09/1990", "Ford" };
    Racer *r3 = new Racer{ "Howard", "male", "18/04/1985", "Dodge" };

    Car c1{ "Ford", "Mustang GT350R", r1, r2 };
    Car c2{ "Dodge", "Challenger SRT Hellcat RedEye", r3 };
}

I expected that using optional would allow me to not have to provide a co-driver when making a new instance of Car. This however does not seem to be the case since I'm getting an error that there is no such constructor.

Brent
  • 328
  • 4
  • 11
  • I think you're looking for default arguments, not `std::optional`. So knowing "*how to properly use std::optional*" wouldn't help you at all. – melpomene Jun 07 '19 at 15:35
  • I think the quick fix is to add a default value `= std::nullopt` to codriver. But I don't think this does exactly what you want it to: you might as well store NULL or nullptr for codriver if you're accepting pointers. I expect someone can write an answer discussing that better than I can. – Rup Jun 07 '19 at 15:35
  • 1
    That's not how `std::optional` works. You still need to pass one. If you don't want a value, then pass an empty optional or an `std::nullopt`. You then check if it has a value either by checking its `true` or `false` value, or by calling its `has_value()` function. – Nikos C. Jun 07 '19 at 15:36
  • Ok so it doesn't do with I thought it would. I will find another solution then. Thank you all for your help! – Brent Jun 07 '19 at 15:39

3 Answers3

2

You can set a default argument for the option:

Car(string make, string model, Racer *driver, optional<Racer*> codriver=std::nullopt) 
   : m_make(make), m_model(model), m_driver(driver), m_codriver(codriver) { }

But as Deduplicator said, this can also be done by using pointers as an option type (null/not-null):

Car(string make, string model, Racer *driver, Racer* codriver=nullptr) 
   : m_make(make), m_model(model), m_driver(driver), m_codriver(codriver) { }
Kostas
  • 4,061
  • 1
  • 14
  • 32
1

If you want an optional argument for a function or ctor, either write two which differ in arity, or use a default-argument (= whatever directly after the optional parameter-name).
Neither option has anything to do with std::optional.

Anyway, when you use std::optional<some_pointer_type>, be aware that all pointers can be null anyway. Or put another way, they are all instances of std::optional<non_nullable_pointer>. So how does a null pointer differ from getting no pointer in your case?

As an aside, it's int main().

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
1

For what you want to do, it seems like setting a default value in the public section of your class should work, as in the following (code taken from this question):

class foo  
{
private:
    std::string name_;
    unsigned int age_;
public:
    foo() :
    name_(""),           // Set your default values here
    age_(0)
{
}

foo(const std::string& name, const unsigned int age) :
        name_(name),
        age_(age)
    {
        ...
    }
};
manny
  • 338
  • 1
  • 11