1 #pragma once
2 
3 #include <initializer_list>
4 #include <utility>
5 
6 #include <absl/types/optional.h>
7 
8 #include "chainerx/macro.h"
9 
10 namespace chainerx {
11 
12 template <typename Container>
13 class OptionalContainerArg {
14 public:
15     using T = typename Container::value_type;
16 
17     // ctor for null value
OptionalContainerArg(absl::nullopt_t)18     OptionalContainerArg(absl::nullopt_t /*nullopt*/) : opt_{absl::nullopt} {}  // NOLINT
19 
20     // ctor for single value
OptionalContainerArg(const T & value)21     OptionalContainerArg(const T& value) : opt_{Container{{value}}} {}  // NOLINT
22 
23     // ctors for vector value
OptionalContainerArg(std::initializer_list<T> list)24     OptionalContainerArg(std::initializer_list<T> list) : opt_{Container{list.begin(), list.end()}} {}
OptionalContainerArg(const Container & v)25     OptionalContainerArg(const Container& v) : opt_{v} {}  // NOLINT
OptionalContainerArg(Container && v)26     OptionalContainerArg(Container&& v) : opt_{std::move(v)} {}  // NOLINT
27 
has_value()28     bool has_value() const { return opt_.has_value(); }
29 
value()30     Container& value() { return opt_.value(); }
31 
value()32     const Container& value() const { return opt_.value(); }
33 
34     Container& operator*() {
35         CHAINERX_ASSERT(has_value());
36         return *opt_;
37     }
38 
39     const Container& operator*() const {
40         CHAINERX_ASSERT(has_value());
41         return *opt_;
42     }
43 
44     Container* operator->() {
45         CHAINERX_ASSERT(has_value());
46         return &*opt_;
47     }
48 
49     const Container* operator->() const {
50         CHAINERX_ASSERT(has_value());
51         return &*opt_;
52     }
53 
54     explicit operator bool() const { return has_value(); }
55 
56 private:
57     absl::optional<Container> opt_;
58 };
59 
60 }  // namespace chainerx
61