Alias std::launder when it is available
[folly.git] / folly / lang / Launder.h
1 /*
2  * Copyright 2017-present Facebook, Inc.
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 <new>
20
21 #include <folly/CPortability.h>
22 #include <folly/Portability.h>
23
24 /***
25  *  include or backport:
26  *  * std::launder
27  */
28
29 #if __cpp_lib_launder >= 201606
30
31 namespace folly {
32
33 /* using override */ using std::launder;
34
35 } // namespace folly
36
37 #else
38
39 namespace folly {
40
41 /**
42  * Approximate backport from C++17 of std::launder. It should be `constexpr`
43  * but that can't be done without specific support from the compiler.
44  */
45 template <typename T>
46 FOLLY_NODISCARD inline T* launder(T* in) noexcept {
47 #if FOLLY_HAS_BUILTIN(__builtin_launder) || __GNUC__ >= 7
48   // The builtin has no unwanted side-effects.
49   return __builtin_launder(in);
50 #elif __GNUC__
51   // This inline assembler block declares that `in` is an input and an output,
52   // so the compiler has to assume that it has been changed inside the block.
53   __asm__("" : "+r"(in));
54   return in;
55 #elif defined(_WIN32)
56   // MSVC does not currently have optimizations around const members of structs.
57   // _ReadWriteBarrier() will prevent compiler reordering memory accesses.
58   _ReadWriteBarrier();
59   return in;
60 #else
61   static_assert(
62       false, "folly::launder is not implemented for this environment");
63 #endif
64 }
65
66 /* The standard explicitly forbids laundering these */
67 void launder(void*) = delete;
68 void launder(void const*) = delete;
69 void launder(void volatile*) = delete;
70 void launder(void const volatile*) = delete;
71 template <typename T, typename... Args>
72 void launder(T (*)(Args...)) = delete;
73 } // namespace folly
74
75 #endif