userver: userver/compiler/select.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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