Skip to main content

reflection-inlines.h File

C++ header file with inline implementations for the µTest++ reflection utilities. More...

Included Headers​

#include <cstdint>

Namespaces Index​

namespacemicro_os_plus

The primary namespace for the µOS++ framework. More...

namespacemicro_test_plus

Primary namespace for the µTest++ testing framework. More...

namespacereflection

Reflection utilities for the µTest++ testing framework. More...

Functions Index​

template <class T>
constexpr std::string_viewtype_name (void)

Extracts the type name from the __PRETTY_FUNCTION__ identifier. More...

Description​

C++ header file with inline implementations for the µTest++ reflection utilities.

This header provides the inline implementations for the reflection utilities used within the µTest++ framework. It includes the logic for capturing and reporting source location information, such as file names and line numbers, as well as utilities for extracting type names at compile time using compiler-specific macros.

The source_location implementation offers a lightweight, constexpr-compatible alternative to std::source_location, used when the standard library does not provide it. The type_name utility parses the compiler-specific __PRETTY_FUNCTION__ string to obtain human-readable type names for improved test output and debugging.

All definitions reside within the micro_os_plus::micro_test_plus::reflection namespace.

This file is included by reflection.h; the applications include micro-os-plus/micro-test-plus.h, not this file.

Functions​

type_name()​

template <class T>
std::string_view micro_os_plus::micro_test_plus::reflection::type_name (void)
nodiscard constexpr

Extracts the type name from the __PRETTY_FUNCTION__ identifier.

This function template parses the compiler-specific __PRETTY_FUNCTION__ identifier to extract a concise type name for the template parameter T.

Rather than relying on fixed character offsets (which are fragile across compiler versions and namespace changes), the implementation searches for the marker that introduces the template argument in the function signature string:

  • Clang formats the signature as "... [T = <typename>]", so the type name lies between the first "[T = " and the last ']'. The marker is searched for as a whole, since the type name may itself contain brackets (e.g. int[3]).
  • GCC formats the signature as "... [with T = <typename>]" or, on some versions, "... [with T = <typename>; ...]", so the type name starts after the first "[with T = " and ends at the following ';' or, if there is none, at the last ']'.

If the marker is not found, or the compiler is not supported (e.g. MSVC, which uses __FUNCSIG__ instead of __PRETTY_FUNCTION__), the function returns "unknown" rather than failing to compile, since the name is used only to improve the test output.

The expected layouts are verified at compile time by the static_assert checks that follow the definition.

The name is spelled as the compiler prints it, and is used to identify the expected exception type in the throws<E> failure messages. Only clang and GCC are supported; with other compilers the function returns "unknown".

Template Parameters
T

The type whose name is to be extracted.

Parameters

None.

Returns

A std::string_view containing the extracted type name, or "unknown" if it cannot be determined.

Definition at line 149 of file reflection-inlines.h.

149 type_name (void) -> std::string_view
150 {
151#if defined(__clang__)
152 // Clang: "... [T = <typename>]"
153 const std::string_view sv = __PRETTY_FUNCTION__;
154 constexpr std::string_view marker{ "[T = " };
155 const auto pos = sv.find (marker);
156 const auto end = sv.rfind (']');
157#elif defined(__GNUC__)
158 // GCC: "... [with T = <typename>]" or, on some versions,
159 // "... [with T = <typename>; std::string_view = ...]"
160 const std::string_view sv = __PRETTY_FUNCTION__;
161 constexpr std::string_view marker{ "[with T = " };
162 const auto pos = sv.find (marker);
163 const auto semi = sv.find (';', pos);
164 const auto end
165 = (semi != std::string_view::npos) ? semi : sv.rfind (']');
166#else
167 // Unsupported compiler; no portable signature string is available.
168 const std::string_view sv{};
169 constexpr std::string_view marker{};
170 const auto pos = std::string_view::npos;
171 const auto end = std::string_view::npos;
172#endif // defined(__clang__) || defined(__GNUC__)
173 if (pos == std::string_view::npos || end == std::string_view::npos
174 || end < pos + marker.size ())
175 {
176 return "unknown";
177 }
178 const auto start = pos + marker.size ();
179 return sv.substr (start, end - start);
180 }

Reference micro_os_plus::micro_test_plus::reflection::type_name.

Referenced by micro_os_plus::micro_test_plus::detail::expression_formatter::operator<< and micro_os_plus::micro_test_plus::reflection::type_name.

File Listing​

The file content with the documentation metadata removed is:

1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can be
9 * obtained from https://opensource.org/licenses/mit.
10 *
11 * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
12 * released under the terms of the Boost Version 1.0 Software License,
13 * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14 */
15
16// ----------------------------------------------------------------------------
17
42
43#ifndef MICRO_OS_PLUS_MICRO_TEST_PLUS_INLINES_REFLECTION_INLINES_H_
44#define MICRO_OS_PLUS_MICRO_TEST_PLUS_INLINES_REFLECTION_INLINES_H_
45
46// ----------------------------------------------------------------------------
47
48#if defined(__cplusplus)
49
50// ----------------------------------------------------------------------------
51
52#include <cstdint>
53
54// ----------------------------------------------------------------------------
55
56#if defined(__GNUC__)
57#pragma GCC diagnostic push
58
59#pragma GCC diagnostic ignored "-Waggregate-return"
60#if defined(__clang__)
61#pragma clang diagnostic ignored "-Wc++98-compat"
62#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
63#endif // defined(__clang__)
64#endif // defined(__GNUC__)
65
66// ============================================================================
67
69{
70 // --------------------------------------------------------------------------
71
72 namespace reflection
73 {
74 // ------------------------------------------------------------------------
75
76#if !defined(__cpp_lib_source_location)
77
86 constexpr source_location
87 source_location::current (const char* file, unsigned int line) noexcept
88 {
90 sl.file_ = file;
91 sl.line_ = line;
92 return sl;
93 }
94
100 constexpr auto
101 source_location::file_name (void) const noexcept
102 {
103 return file_;
104 }
105
111 constexpr auto
112 source_location::line (void) const noexcept
113 {
114 return line_;
115 }
116
117#endif // !defined(__cpp_lib_source_location)
118
147 template <class T>
148 constexpr auto
149 type_name (void) -> std::string_view
150 {
151#if defined(__clang__)
152 // Clang: "... [T = <typename>]"
153 const std::string_view sv = __PRETTY_FUNCTION__;
154 constexpr std::string_view marker{ "[T = " };
155 const auto pos = sv.find (marker);
156 const auto end = sv.rfind (']');
157#elif defined(__GNUC__)
158 // GCC: "... [with T = <typename>]" or, on some versions,
159 // "... [with T = <typename>; std::string_view = ...]"
160 const std::string_view sv = __PRETTY_FUNCTION__;
161 constexpr std::string_view marker{ "[with T = " };
162 const auto pos = sv.find (marker);
163 const auto semi = sv.find (';', pos);
164 const auto end
165 = (semi != std::string_view::npos) ? semi : sv.rfind (']');
166#else
167 // Unsupported compiler; no portable signature string is available.
168 const std::string_view sv{};
169 constexpr std::string_view marker{};
170 const auto pos = std::string_view::npos;
171 const auto end = std::string_view::npos;
172#endif // defined(__clang__) || defined(__GNUC__)
173 if (pos == std::string_view::npos || end == std::string_view::npos
174 || end < pos + marker.size ())
175 {
176 return "unknown";
177 }
178 const auto start = pos + marker.size ();
179 return sv.substr (start, end - start);
180 }
181
182#if defined(__GNUC__)
183 // Compile-time self-test of the signature layout parsed above; a
184 // failure means that the compiler changed its __PRETTY_FUNCTION__
185 // format and `type_name()` must be updated.
186 static_assert (type_name<int> () == "int");
187 static_assert (type_name<unsigned int> () == "unsigned int");
188 static_assert (type_name<int[3]> () == "int [3]"
189 || type_name<int[3]> () == "int[3]");
190#endif // defined(__GNUC__)
191
192 // ------------------------------------------------------------------------
193 } // namespace reflection
194
195 // --------------------------------------------------------------------------
196} // namespace micro_os_plus::micro_test_plus
197
198#if defined(__GNUC__)
199#pragma GCC diagnostic pop
200#endif // defined(__GNUC__)
201
202// ----------------------------------------------------------------------------
203
204#endif // defined(__cplusplus)
205
206// ----------------------------------------------------------------------------
207
208#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_INLINES_REFLECTION_INLINES_H_
209
210// ----------------------------------------------------------------------------

Generated via doxygen2docusaurus 2.2.8 by Doxygen 1.18.0.