C++Spec 1.0.0
BDD testing for C++
Loading...
Searching...
No Matches
util.hpp
Go to the documentation of this file.
1
5#pragma once
6#include <functional>
7#include <ranges>
8#include <sstream>
9#include <string>
10#include <type_traits>
11
12#ifdef __GNUG__
13#include <cxxabi.h>
14
15#include <memory>
16
17#endif
18
19namespace CppSpec::Util {
20
28#ifdef __GNUG__
29inline std::string demangle(const char* mangled) {
30 int status;
31 std::unique_ptr<char[], void (*)(void*)> result{
32 abi::__cxa_demangle(mangled, nullptr, nullptr, &status),
33 std::free,
34 };
35 return (status == 0) ? result.get() : mangled;
36}
37#else
38inline std::string demangle(const char* name) {
39 return name;
40}
41#endif
42
46template <bool result>
48 static_assert(result, "Assertion failed (see below for more information)");
49 static bool const value = result;
50};
51
64template <typename C>
65concept is_container = requires(C c) {
66 requires std::ranges::range<C>;
67 { c.max_size() } -> std::integral;
68 { c.empty() } -> std::convertible_to<bool>;
69};
70
80template <typename C>
81concept is_streamable = requires(std::ostream& os, const C& obj) {
82 { os << obj } -> std::same_as<std::ostream&>;
83};
84
85template <typename C>
87 // The C++ reference says that all "functions" (not FunctionObjects) respond to
88 // std::is_function<T>
89 std::is_function_v<C> ||
90
91 // An alternative from Stack Overflow question 18107368. Anything that could
92 // possibly be "functional" should be able to be cast to std::function<void()>
93 std::is_convertible_v<C, std::function<void()>> ||
94
95 // The C++ reference also says that something qualifies as a FunctionObject iff
96 // std::is_object_v<T> is true and the object responds to the call operator()
97 requires(C func) {
98 requires std::is_object_v<C>;
99 { func() } -> std::invocable<>;
100 };
101
102template <typename C>
104
105template <typename T>
106concept not_c_string = !std::is_same_v<T, const char*> && !std::is_same_v<T, char*> &&
107 !std::is_convertible_v<T, const char*> && !std::is_convertible_v<T, char*>;
108
119[[nodiscard]] inline std::string join(std::ranges::range auto& iterable, const std::string& separator = "") {
120 std::ostringstream oss;
121 bool first = true;
122 for (auto& thing : iterable) {
123 if (!first) {
124 oss << separator;
125 }
126 oss << thing; // use operator<< to convert and append
127 first = false;
128 }
129 return oss.str();
130}
131
132[[nodiscard]] inline std::string join_endl(std::ranges::range auto&& iterable) {
133 std::ostringstream oss;
134 bool first = true;
135 for (auto& thing : iterable) {
136 if (!first) {
137 oss << std::endl;
138 }
139 oss << thing; // use operator<< to convert and append
140 first = false;
141 }
142 return oss.str();
143}
144
145} // namespace CppSpec::Util
Concept for checking whether T is a container type.
Definition util.hpp:65
Definition util.hpp:86
Definition util.hpp:103
Checks whether T can be streamed.
Definition util.hpp:81
Definition util.hpp:106
Helper class for static assertions that has a built-in error string.
Definition util.hpp:47
std::string demangle(const char *name)
Definition util.hpp:38
std::string join(std::ranges::range auto &iterable, const std::string &separator="")
Implode a string.
Definition util.hpp:119