VLink 2.0.0
A high-performance communication middleware
载入中...
搜索中...
未找到
name_detector.h
浏览该文件的文档.
1/*
2 * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 * Author: Thun Lu <thun.lu@zohomail.cn>
4 * Repo: https://github.com/thun-res/vlink
5 * _ __ __ _ __
6 * | | / / / / (_) ____ / /__
7 * | | / / / / / / / __ \ / //_/
8 * | |/ / / /___ / / / / / / / ,<
9 * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/**
25 * @file name_detector.h
26 * @brief Compile-time type-name and enum-name detection utilities.
27 *
28 * @details
29 * The @c vlink::NameDetector namespace wraps the third-party @c nameof library
30 * to provide a portable, @c constexpr API for obtaining the string representation
31 * of a type or an enumeration value at compile time.
32 *
33 * These utilities are used by the VLink plugin system to automatically derive
34 * plugin identifiers from interface class names, avoiding error-prone manual
35 * string registration.
36 *
37 * Platform notes:
38 * - On Windows (MSVC / MSYS2) the @c nameof library may prefix types with
39 * @c "struct " or @c "class ". @c NameDetector::get() strips these prefixes
40 * automatically to return only the unqualified type name.
41 * - On GCC/Clang the result of @c nameof::nameof_type<T>() is used directly.
42 *
43 * @note
44 * The @c get<T>() function returns a @c constexpr @c std::string_view that
45 * points into static storage generated by the compiler. The view is valid for
46 * the entire program lifetime.
47 *
48 * @par Example
49 * @code
50 * // Check support and get the type name:
51 * if constexpr (vlink::NameDetector::is_support<MyPlugin>()) {
52 * constexpr std::string_view name = vlink::NameDetector::get<MyPlugin>();
53 * // name == "MyPlugin"
54 * }
55 *
56 * // Get enum value name at runtime:
57 * enum class Color { Red, Green, Blue };
58 * std::string_view name = vlink::NameDetector::get_enum(Color::Green);
59 * // name == "Green"
60 * @endcode
61 */
62
63#pragma once
64
65#include <string_view>
66
67#include "../thirdparty/nameof.h"
68
69namespace vlink {
70
71/**
72 * @namespace vlink::NameDetector
73 * @brief Compile-time type-name and enum-name detection utilities.
74 */
75namespace NameDetector { // NOLINT(readability-identifier-naming)
76
77/**
78 * @brief Checks at compile time whether the @c nameof library can produce a
79 * type name for @p T.
80 *
81 * @details
82 * Returns @c true when the underlying @c nameof::detail::nameof_type_supported
83 * trait evaluates to @c true for @p T. When this returns @c false, calling
84 * @c get<T>() may produce an empty or implementation-defined string.
85 *
86 * @tparam T The type to check.
87 * @return @c true if type-name detection is supported for @p T.
88 */
89template <typename T>
90[[nodiscard]] constexpr bool is_support() noexcept;
91
92/**
93 * @brief Returns the unqualified compile-time name of type @p T as a
94 * @c std::string_view.
95 *
96 * @details
97 * On Windows, leading @c "struct " and @c "class " prefixes that MSVC may
98 * inject are stripped before returning. On other platforms the raw
99 * @c nameof::nameof_type<T>() result is returned.
100 *
101 * The returned view points to static storage (lifetime of the program).
102 * It is used by the VLink plugin system to register interfaces by their
103 * type name rather than by a manually specified string.
104 *
105 * @tparam T The type whose name is requested.
106 * @return A @c constexpr @c std::string_view containing the type name.
107 *
108 * @note
109 * This function is @c constexpr on supported compilers. The result is
110 * identical whether evaluated at compile time or runtime.
111 */
112template <typename T>
113[[nodiscard]] constexpr std::string_view get() noexcept;
114
115/**
116 * @brief Returns the string representation of an enumeration value @p e.
117 *
118 * @details
119 * Wraps @c nameof::nameof_enum to obtain the enumerator name. Returns
120 * an empty @c std::string_view if the value is out of the known range.
121 *
122 * @tparam T The enumeration type.
123 * @param e The enumeration value to name.
124 * @return A @c std::string_view containing the enumerator name, or an
125 * empty view if @p e is not a named enumerator.
126 */
127template <typename T>
128[[nodiscard]] std::string_view get_enum(T e) noexcept;
129
130} // namespace NameDetector
131
132////////////////////////////////////////////////////////////////
133/// Details
134////////////////////////////////////////////////////////////////
135
136template <typename T>
137inline constexpr bool NameDetector::is_support() noexcept {
138 if constexpr (nameof::detail::nameof_type_supported<T>::value) {
139 return true;
140 } else {
141 return false;
142 }
143}
144
145template <typename T>
146inline constexpr std::string_view NameDetector::get() noexcept {
147#if defined(_WIN32) || defined(__CYGWIN__)
148 std::string_view type_sv = nameof::nameof_type<T>();
149
150 constexpr std::string_view kStructPrefix = "struct ";
151 if (type_sv.rfind(kStructPrefix, 0) == 0) {
152 type_sv.remove_prefix(kStructPrefix.length());
153 }
154
155 constexpr std::string_view kClassPrefix = "class ";
156 if (type_sv.rfind(kClassPrefix, 0) == 0) {
157 type_sv.remove_prefix(kClassPrefix.length());
158 }
159
160 return type_sv;
161#else
162 return nameof::nameof_type<T>();
163#endif
164}
165
166template <typename T>
167inline std::string_view NameDetector::get_enum(T e) noexcept {
168 return nameof::nameof_enum(e);
169}
170
171} // namespace vlink