1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <memory>
20 #include <utility>
21 
22 #include <folly/Overload.h>
23 #include <thrift/lib/cpp2/Thrift.h>
24 
25 namespace apache {
26 namespace thrift {
27 
28 //  IndirectionWrapper
29 //
30 //  Owns a value of type T, which may be incomplete at instantiation time.
31 //
32 //  Provides access to the T and works with cpp.indirection.
33 //
34 //  Expected to be used as a base class. Enforced by marking the dtor protected.
35 template <typename Derived, typename T>
36 class IndirectionWrapper {
37  private:
38   std::unique_ptr<T> raw_{new T()};
39 
40  protected:
41   ~IndirectionWrapper() = default;
42 
43  public:
44   FBTHRIFT_CPP_DEFINE_MEMBER_INDIRECTION_FN(__fbthrift_data());
45 
46   IndirectionWrapper() = default;
47 
IndirectionWrapper(const IndirectionWrapper & other)48   IndirectionWrapper(const IndirectionWrapper& other)
49       : raw_(new T(other.__fbthrift_data())) {}
50 
noexcept(false)51   IndirectionWrapper(IndirectionWrapper&& other) noexcept(false)
52       : raw_(new T(std::move(other.__fbthrift_data()))) {}
53 
noexcept(std::is_nothrow_copy_assignable_v<T>)54   IndirectionWrapper& operator=(const IndirectionWrapper& other) noexcept(
55       std::is_nothrow_copy_assignable_v<T>) {
56     __fbthrift_data() = other.__fbthrift_data();
57     return *this;
58   }
59 
noexcept(std::is_nothrow_move_assignable_v<T>)60   IndirectionWrapper& operator=(IndirectionWrapper&& other) noexcept(
61       std::is_nothrow_move_assignable_v<T>) {
62     __fbthrift_data() = std::move(other.__fbthrift_data());
63     return *this;
64   }
65 
66   friend bool operator==(const Derived& lhs, const Derived& rhs) {
67     return lhs.__fbthrift_data() == rhs.__fbthrift_data();
68   }
69 
70   friend bool operator<(const Derived& lhs, const Derived& rhs) {
71     return lhs.__fbthrift_data() < rhs.__fbthrift_data();
72   }
73 
__fbthrift_data()74   T& __fbthrift_data() & { return *raw_; }
75 
__fbthrift_data()76   const T& __fbthrift_data() const& { return *raw_; }
77 
__fbthrift_data()78   T&& __fbthrift_data() && { return std::move(*raw_); }
79 
__fbthrift_data()80   const T&& __fbthrift_data() const&& { return std::move(*raw_); }
81 
82  private:
83   friend struct apache::thrift::detail::st::struct_private_access;
84 
__fbthrift_clear()85   void __fbthrift_clear() { apache::thrift::clear(__fbthrift_data()); }
86 };
87 } // namespace thrift
88 } // namespace apache
89