Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I return an optional from a constexpr function?

  • Can I return an optional from a constexpr function?
  • Why?
  • If yes, how does it work?

I'm interested in both boost::optional and std::optional. Do they behave the same?

like image 272
gnzlbg Avatar asked May 07 '13 13:05

gnzlbg


People also ask

Can a function return Constexpr?

Unlike const , constexpr can also be applied to functions and class constructors. constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time.

Does STD optional allocate?

optional is required to not use dynamic allocation. If an optional contains a value, the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place.

How does STD optional work?

std::optional contains the object within itself, depending on where it is stored (stack/data/heap) std::optional makes a copy of the contained object. Monadic functions will be added in C++23 to improve the abstraction in our code by removing the needs of writing boilerplate code.

Does STD optional allocate memory?

What's more, std::optional doesn't need to allocate any memory on the free store. std::optional is a part of C++ vocabulary types along with std::any , std::variant and std::string_view .


2 Answers

boost::optional cannot be returned by a constexpr function. Or at least, the documentation provides no guarantees of this.

However, std::optional, as defined by the accepted C++14 proposal, can be returned by a constexpr function. But only if the type argument of the optional is trivially destructible.

This allows the destructor of std::optional to be trivial in those cases. At which point, there's no difficulty in destroying the object, so there's nothing stopping std::optional from being a literal type.

The proposal is quite clear on this. If T is trivially destructible, then most of the constructors of optional will be constexpr, and optional<T> will be a literal type. And therefore, it can be created in a constexpr function.

like image 165
Nicol Bolas Avatar answered Oct 21 '22 13:10

Nicol Bolas


Boost.Optional does not support constexpr, mainly because it was written before C++11 was released.

The current proposal for std::optional does support constexpr, as long as the value type T is trivially destructible. It works because constexpr constructors are allowed for unions (7.1.5p4); the compiler tracks which union member is initialized, ensuring that the undefined behaviour of accessing the value of a disengaged optional is caught at compile time:

struct dummy_t {};
template <class T>
union optional_storage {
  static_assert( is_trivially_destructible<T>::value, "" );
  dummy_t dummy_;
  T       value_;
  constexpr optional_storage(): dummy_{} {}  // disengaged
  constexpr optional_storage(T const& v): value_{v} {}  // engaged
  ~optional_storage() = default;
};

The value type must be trivially destructible because constexpr is only useful with literal types, which must themselves have a trivial destructor.

For example, writing:

constexpr optional_storage<int> o{};
constexpr int i = o.value_;

gcc gives the error:

error: accessing ‘optional_storage<int>::value_’ member instead of initialized 
‘optional_storage<int>::dummy_’ member in constant expression
like image 32
ecatmur Avatar answered Oct 21 '22 13:10

ecatmur