15

I need to implement a quick solution for optional values. I don't want to drag in any third party libraries.

How are the optional classes implemented in general? Does an optional object still default-construct the underlying object when it's in the 'null-state'?

NFRCR
  • 5,304
  • 6
  • 32
  • 37
  • 3
    Have you looked into the [Boost.Optional](http://www.boost.org/doc/libs/1_56_0/libs/optional/doc/html/index.html) implementation? – Angew is no longer proud of SO Sep 15 '14 at 09:21
  • The C++ standard library isn't a third party library. I suppose you do not wish to start using C++14 yet? – E_net4 Sep 15 '14 at 09:22
  • @E_net4 My compiler does not support it yet. – NFRCR Sep 15 '14 at 09:23
  • cut/paste boost::optional – bobah Sep 15 '14 at 09:26
  • 5
    Basically speaking, Boost.Optional (as suggested by Angew) is what was eventually accepted as std::optional. So if you're burdened with an old(er) compiler, Boost.Optional is the way to go. (Similar with e.g. Boost.smart_ptr and std::shared_ptr.) I understand the reluctance regarding third-party libraries, but C++ without Boost is bound to reinvent much-proven wheels. – DevSolar Sep 15 '14 at 09:27
  • Look at [this thread and the related comments](http://stackoverflow.com/questions/11875045/implementing-boostoptional-in-c11) for a quick-and-dirty implementation (-- if you definitely have no way to include the std or boost optional class) – davidhigh Sep 15 '14 at 12:27

5 Answers5

14

How are the optional classes implemented in general?

Typically, a boolean flag to indicate whether or not it's empty, and a suitably sized and aligned byte array to store the value.

Does an optional object still default-construct the underlying object when it's in the 'null-state'?

No; that would impose an unnecessary requirement on the stored type, as well as causing potential unwanted side-effects. The stored object would be created with placement-new when the optional becomes non-empty, and destroyed with a destructor call when it becomes empty.

For a quick-and-dirty implementation, if you don't need all the flexibility of the Boost or proposed standard versions, you could simply store a default-constructed object.

I don't want to drag in any third party libraries.

I would reconsider why you don't feel you want that. The Boost implementation is header-only, well tested, and should be directly replaceable by the standard version if and when that arrives. I'd certainly trust it more than something I cobbled together myself.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
3

First of all I highly recommend you to take a look at Boost (specifically at Boost.Optional) - it is almost standard practice to use Boost and it would save you reinventing the wheel.

If for some reason you are reluctant to use Boost.Optional, there are a bunch of similar header-only libraries, for example https://github.com/akrzemi1/Optional

pdeschain
  • 1,411
  • 12
  • 21
1

In or earlier you can use a null-checked T* or just a std::pair<T, bool>. The problem with the latter is if your default construction of T is expensive, that may be wasteful.

In or later you can still use T* but you can also use std::optional<T>. Here the latter only constructs a T if it is valid.

It's noteworthy that the std::optional is a good option in only a few cases: https://topanswers.xyz/cplusplus?q=923#a1085

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 6
    I disagree that `std::optional` is a good option in only a few cases. The point of using `std::optional` instead of `T*` is that `std::optional` contains a `T` directly so that you don't need an extra layer of indirection to represent an owned maybe non-existent value. – cuddlebugCuller Oct 06 '20 at 22:14
  • 1
    I agree with cuddlebugCuller. What's more, the interface is much clearer than a rare pointer that does not say anything about whether it could be nullptr – IceFire Mar 12 '21 at 07:14
  • "null-checked `T*`" - specifically, you could use `std::unique_ptr` – Arthur Tacca Jul 14 '23 at 09:40
0

std::optional from Scratch introduces how to implement a optional class

Like
  • 1,470
  • 15
  • 21
-1

Here is a start to mimicking std::optional. Not the trickiest implementation and has a lot more that should be added.

template <typename T>
struct optional {
private:
    bool _has_value;
    T _value;
public:
    optional() : _has_value{false}, _value{} {}
    optional(T v) : _has_value{true}, _value{v} {}
    bool has_value() const {return _has_value;}
    T value() const {
        if (_has_value) return _value;
        throw std::bad_optional_access();
    }
    T value_or(T def) const {
        return _has_value ? _value : def;
    }
    optional<T>& operator=(T v) {
        _has_value = true;
        _value = v;
        return *this;
    }
    void reset() {_has_value = false;}
};
wcochran
  • 10,089
  • 6
  • 61
  • 69