cpp-stat-bench 0.24.0
Benchmark library with statistics for C++.
Loading...
Searching...
No Matches
parameter_value.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 MusicScience37 (Kenta Kabashima)
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 */
20#pragma once
21
22#include <cstddef>
23#include <cstdint>
24#include <functional>
25#include <memory>
26#include <string>
27#include <type_traits>
28#include <typeindex>
29#include <typeinfo>
30#include <utility>
31#include <variant>
32
33#include <fmt/format.h>
34
37
38namespace stat_bench {
39namespace param {
40
45 std::variant<bool, std::intmax_t, std::uintmax_t, long double, std::string>;
46
52template <typename T>
59 [[nodiscard]] static auto get_type() -> const std::type_info& {
60 return typeid(T);
61 }
62
69 [[nodiscard]] static auto to_string(const std::shared_ptr<void>& data)
71 return util::Utf8String(
72 fmt::format("{}", *static_cast<const T*>(data.get())));
73 }
74
81 [[nodiscard]] static auto to_double(const std::shared_ptr<void>& data)
82 -> double {
83 if constexpr (std::is_convertible_v<T, double>) {
84 return static_cast<double>(*static_cast<const T*>(data.get()));
85 } else {
87 fmt::format("Cannot convert {} to double.", typeid(T).name()));
88 }
89 }
90
97 [[nodiscard]] static auto to_variant(const std::shared_ptr<void>& data)
99 if constexpr (std::is_same_v<T, bool>) {
100 return *static_cast<const bool*>(data.get());
101 } else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>) {
102 return static_cast<std::intmax_t>(
103 *static_cast<const T*>(data.get()));
104 } else if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>) {
105 return static_cast<std::uintmax_t>(
106 *static_cast<const T*>(data.get()));
107 } else if constexpr (std::is_floating_point_v<T>) {
108 return static_cast<long double>(*static_cast<const T*>(data.get()));
109 } else if constexpr (std::is_same_v<T, std::string>) {
110 return *static_cast<const std::string*>(data.get());
111 } else {
112 return fmt::format("{}", *static_cast<const T*>(data.get()));
113 }
114 }
115
122 [[nodiscard]] static auto calculate_hash(const std::shared_ptr<void>& data)
123 -> std::size_t {
124 return std::hash<std::type_index>{}(std::type_index(typeid(T))) ^
125 std::hash<T>{}(*static_cast<const T*>(data.get()));
126 }
127
136 [[nodiscard]] static auto equal(const std::shared_ptr<void>& data1,
137 const std::shared_ptr<void>& data2) -> bool {
138 return *static_cast<const T*>(data1.get()) ==
139 *static_cast<const T*>(data2.get());
140 }
141};
142
147public:
151 ParameterValue() noexcept = default;
152
161 template <typename T, typename... Args>
162 auto emplace(Args&&... args) -> ParameterValue& {
163 data_ = std::make_shared<T>(std::forward<Args>(args)...);
170 return *this;
171 }
172
176 void clear() noexcept { data_.reset(); }
177
184 template <typename T>
185 [[nodiscard]] auto is_type_of() const -> bool {
186 if (!data_) {
187 return false;
188 }
189 return get_type_() == typeid(T);
190 }
191
198 template <typename T>
199 [[nodiscard]] auto as() const -> const T& {
200 if (!data_) {
201 throw StatBenchException(
202 "Tried to get value from empty ParameterValue object.");
203 }
204 if (!is_type_of<T>()) {
205 throw StatBenchException(fmt::format(
206 "Wrong type of parameter value (expected: {}, actual: {}).",
207 typeid(T).name(), get_type_().name()));
208 }
209 return *static_cast<const T*>(data_.get());
210 }
211
217 [[nodiscard]] auto to_string() const -> util::Utf8String {
218 if (!data_) {
219 return util::Utf8String("null");
220 }
221 return to_string_(data_);
222 }
223
229 [[nodiscard]] auto to_double() const -> double {
230 if (!data_) {
231 throw StatBenchException(
232 "Tried to convert an empty ParameterValue object to double.");
233 }
234 return to_double_(data_);
235 }
236
242 [[nodiscard]] auto to_variant() const -> ParameterValueVariant {
243 if (!data_) {
244 throw StatBenchException(
245 "Tried to convert an empty ParameterValue object to a variant "
246 "object.");
247 }
248 return to_variant_(data_);
249 }
250
256 [[nodiscard]] auto calculate_hash() const -> std::size_t {
257 if (!data_) {
258 return 0;
259 }
260 return calculate_hash_(data_);
261 }
262
270 [[nodiscard]] auto operator==(const ParameterValue& rhs) const -> bool {
271 if (!data_ && !rhs.data_) {
272 return true;
273 }
274 if (!data_ || !rhs.data_) {
275 return false;
276 }
277 if (get_type_() != rhs.get_type_()) {
278 return false;
279 }
280 return equal_(data_, rhs.data_);
281 }
282
290 [[nodiscard]] auto operator!=(const ParameterValue& rhs) const -> bool {
291 return !(*this == rhs);
292 }
293
294private:
296 using GetTypeSignature = const std::type_info&();
297
299 using ToStringSignature = util::Utf8String(const std::shared_ptr<void>&);
300
302 using ToDoubleSignature = double(const std::shared_ptr<void>&);
303
305 using ToVariantSignature = ParameterValueVariant(
306 const std::shared_ptr<void>&);
307
309 using CalculateHashSignature = std::size_t(const std::shared_ptr<void>&);
310
312 using EqualSignature = bool(
313 const std::shared_ptr<void>&, const std::shared_ptr<void>&);
314
316 std::shared_ptr<void> data_{};
317
319 GetTypeSignature* get_type_{nullptr};
320
322 ToStringSignature* to_string_{nullptr};
323
325 ToDoubleSignature* to_double_{nullptr};
326
328 ToVariantSignature* to_variant_{nullptr};
329
331 CalculateHashSignature* calculate_hash_{nullptr};
332
334 EqualSignature* equal_{nullptr};
335};
336
337} // namespace param
338} // namespace stat_bench
339
340namespace std {
341
345template <>
346class hash<stat_bench::param::ParameterValue> {
347public:
355 -> std::size_t {
356 return val.calculate_hash();
357 }
358};
359
360} // namespace std
Class of exceptions in this library.
Class of values of parameters.
auto as() const -> const T &
Get value.
void clear() noexcept
Clear data.
auto calculate_hash() const -> std::size_t
Calculate hash value.
auto operator!=(const ParameterValue &rhs) const -> bool
Check whether two values are not equal.
auto operator==(const ParameterValue &rhs) const -> bool
Check whether two values are equal.
ParameterValue() noexcept=default
Constructor.
auto to_variant() const -> ParameterValueVariant
Convert to a variant object.
auto to_string() const -> util::Utf8String
Format to string.
auto emplace(Args &&... args) -> ParameterValue &
Initialize data.
auto is_type_of() const -> bool
Check data type.
auto to_double() const -> double
Convert to double.
Class of UTF-8 encoded string.
Definition utf8_string.h:35
auto operator()(const stat_bench::param::ParameterValue &val) const -> std::size_t
Hash function.
Namespace of parameters of benchmarks.
std::variant< bool, std::intmax_t, std::uintmax_t, long double, std::string > ParameterValueVariant
Type of variant of parameter values.
Namespace of utility functions and classes.
Namespace of stat_bench source codes.
STL namespace.
Definition of StatBenchException class.
Class of traits of parameter values.
static auto to_double(const std::shared_ptr< void > &data) -> double
Convert to double.
static auto equal(const std::shared_ptr< void > &data1, const std::shared_ptr< void > &data2) -> bool
Check whether two values are equal.
static auto calculate_hash(const std::shared_ptr< void > &data) -> std::size_t
Calculate hash value.
static auto get_type() -> const std::type_info &
Get the type.
static auto to_string(const std::shared_ptr< void > &data) -> util::Utf8String
Format to string.
static auto to_variant(const std::shared_ptr< void > &data) -> ParameterValueVariant
Convert to a variant object.
Definition of Utf8String class.