common/util/cpp/HsOption.h (70 lines of code) (raw):
// Copyright (c) Facebook, Inc. and its affiliates.
#pragma once
#include <folly/Optional.h>
#include <optional>
#include "cpp/HsStructDefines.h"
#include "cpp/Marshallable.h"
// HsOption -------------------------------------------------------------------
#define hsc_derive_hs_option_unsafe(cxx_name...) \
hsc_printf( \
"deriveHsOptionUnsafe \"%s\" %lu ", \
#cxx_name, \
(unsigned long)sizeof(HsOption<hs_option::cxx_name>)); \
hsc_alignment(HsOption<hs_option::cxx_name>);
#define HS_OPTION_H(Name, Type) \
namespace hs_option { \
using Name = Type; \
};
#define HS_OPTION_CPP(Name, Type...) \
extern "C" void* option_newHsOption##Name(Type* v) noexcept { \
return new HsOption<Type>(std::move(*v)); \
} \
extern "C" void option_ctorHsOption##Name(void* ret, Type* v) noexcept { \
new (ret) HsOption<Type>(std::move(*v)); \
} \
HS_PEEKABLE(HsOption<Type>); \
HS_DEFINE_MARSHALLABLE(HsOption##Name, HsOption<Type>);
template <typename T>
HS_STRUCT HsOption {
T* value = nullptr;
std::optional<T> opt = std::nullopt;
public:
HsOption() {}
/* implicit */ HsOption(T && value) : opt(std::move(value)) {
update();
}
template <typename U>
/* implicit */ HsOption(folly::Optional<U> && value) : opt(std::move(value)) {
update();
}
template <typename U>
/* implicit */ HsOption(std::optional<U> && value) : opt(std::move(value)) {
update();
}
HsOption(const HsOption&) = delete;
HsOption(HsOption && other) noexcept : opt(std::move(other.opt)) {
update();
other.opt = std::nullopt; // a moved optional doesn't empty the value
other.update();
}
HsOption& operator=(const HsOption&) = delete;
HsOption& operator=(HsOption&& other) noexcept {
opt = std::move(other.opt);
update();
other.opt = std::nullopt; // a moved optional doesn't empty the value
other.update();
return *this;
}
std::optional<T> toStdOptional()&& {
std::optional<T> res = std::move(opt);
opt = std::nullopt;
update();
return res;
}
private:
void update() {
if (opt.has_value()) {
value = &opt.value();
} else {
value = nullptr;
}
}
};