userver: userver/compiler/select.hpp Source File
Loading...
Searching...
No Matches
select.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/compiler/select.hpp
4/// @brief Utilities for selection of platform specific values
5/// @ingroup userver_universal
6
7#include <cstddef>
8
9USERVER_NAMESPACE_BEGIN
10
11namespace compiler {
12
13namespace impl {
14[[noreturn]] void Abort() noexcept;
15}
16
17/// @brief Selects the proper value for the current compiler and standard
18/// library.
19///
20/// If proper value for the standard library was set, prefers it over the
21/// generic x32/x64 values.
22///
23/// ## Example usage:
24/// @snippet utils/widget_fast_pimpl_test.hpp FastPimpl - header
25template <typename T>
26class SelectValue final {
27public:
28 constexpr SelectValue() = default;
29
30 constexpr SelectValue& ForLibCpp64(T value) noexcept { return Set(Bits::k64, StdLibs::kCpp, value); }
31
32 constexpr SelectValue& ForLibStdCpp64(T value) noexcept { return Set(Bits::k64, StdLibs::kStdCpp, value); }
33
34 constexpr SelectValue& ForLibCpp32(T value) noexcept { return Set(Bits::k32, StdLibs::kCpp, value); }
35
36 constexpr SelectValue& ForLibStdCpp32(T value) noexcept { return Set(Bits::k32, StdLibs::kStdCpp, value); }
37
38 constexpr SelectValue& For64Bit(T value) noexcept { return Set(Bits::k64, StdLibs::kAny, value); }
39
40 constexpr SelectValue& For32Bit(T value) noexcept { return Set(Bits::k32, StdLibs::kAny, value); }
41
42 constexpr operator T() const noexcept {
43 if (has_stdlib_value_) {
44 return stdlib_value_;
45 } else if (has_bits_value_) {
46 return bits_value_;
47 } else {
48 compiler::impl::Abort();
49 }
50 }
51
52private:
53 enum class Bits {
54 k32,
55 k64,
56 };
57
58 enum class StdLibs {
59 kAny,
60 kStdCpp,
61 kCpp,
62 };
63
64 constexpr SelectValue& Set(Bits bits, StdLibs lib, T value) noexcept {
65 constexpr auto kBits = (sizeof(void*) == 8 ? Bits::k64 : Bits::k32);
66 constexpr auto kLib =
67#if defined(_LIBCPP_VERSION)
68 StdLibs::kCpp
69#else
70 StdLibs::kStdCpp
71#endif
72 ;
73
74 if (bits == kBits) {
75 if (lib == kLib) {
76 has_stdlib_value_ = true;
77 stdlib_value_ = value;
78 } else if (lib == StdLibs::kAny) {
79 has_bits_value_ = true;
80 bits_value_ = value;
81 }
82 }
83
84 return *this;
85 }
86
87 T stdlib_value_ = {};
88 T bits_value_ = {};
89 bool has_stdlib_value_ = false;
90 bool has_bits_value_ = false;
91};
92
93/// @brief Alias for std::size_t values selection for the current compiler and
94/// standard library.
95using SelectSize = SelectValue<std::size_t>;
96
97} // namespace compiler
98
99USERVER_NAMESPACE_END