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 {
27 public:
28 constexpr SelectValue() = default;
29
30 constexpr SelectValue& ForLibCpp64(T value) noexcept {
31 return Set(Bits::k64, StdLibs::kCpp, value);
32 }
33
34 constexpr SelectValue& ForLibStdCpp64(T value) noexcept {
35 return Set(Bits::k64, StdLibs::kStdCpp, value);
36 }
37
38 constexpr SelectValue& ForLibCpp32(T value) noexcept {
39 return Set(Bits::k32, StdLibs::kCpp, value);
40 }
41
42 constexpr SelectValue& ForLibStdCpp32(T value) noexcept {
43 return Set(Bits::k32, StdLibs::kStdCpp, value);
44 }
45
46 constexpr SelectValue& For64Bit(T value) noexcept {
47 return Set(Bits::k64, StdLibs::kAny, value);
48 }
49
50 constexpr SelectValue& For32Bit(T value) noexcept {
51 return Set(Bits::k32, StdLibs::kAny, value);
52 }
53
54 constexpr operator T() const noexcept {
55 if (has_stdlib_value_) {
56 return stdlib_value_;
57 } else if (has_bits_value_) {
58 return bits_value_;
59 } else {
60 compiler::impl::Abort();
61 }
62 }
63
64 private:
65 enum class Bits {
66 k32,
67 k64,
68 };
69
70 enum class StdLibs {
71 kAny,
72 kStdCpp,
73 kCpp,
74 };
75
76 constexpr SelectValue& Set(Bits bits, StdLibs lib, T value) noexcept {
77 constexpr auto kBits = (sizeof(void*) == 8 ? Bits::k64 : Bits::k32);
78 constexpr auto kLib =
79#if defined(_LIBCPP_VERSION)
80 StdLibs::kCpp
81#else
82 StdLibs::kStdCpp
83#endif
84 ;
85
86 if (bits == kBits) {
87 if (lib == kLib) {
88 has_stdlib_value_ = true;
89 stdlib_value_ = value;
90 } else if (lib == StdLibs::kAny) {
91 has_bits_value_ = true;
92 bits_value_ = value;
93 }
94 }
95
96 return *this;
97 }
98
99 T stdlib_value_ = {};
100 T bits_value_ = {};
101 bool has_stdlib_value_ = false;
102 bool has_bits_value_ = false;
103};
104
105/// @brief Alias for std::size_t values selection for the current compiler and
106/// standard library.
107using SelectSize = SelectValue<std::size_t>;
108
109} // namespace compiler
110
111USERVER_NAMESPACE_END