Add nameof module support
Some checks failed
macos / macos-13 (push) Has been cancelled
macos / macos-14 (push) Has been cancelled
ubuntu / clang-10 (push) Has been cancelled
ubuntu / clang-11 (push) Has been cancelled
ubuntu / clang-12 (push) Has been cancelled
ubuntu / clang-13 (push) Has been cancelled
ubuntu / clang-14 (push) Has been cancelled
ubuntu / clang-15 (push) Has been cancelled
ubuntu / clang-16 (push) Has been cancelled
ubuntu / clang-9 (push) Has been cancelled
ubuntu / gcc-10 (push) Has been cancelled
ubuntu / gcc-11 (push) Has been cancelled
ubuntu / gcc-12 (push) Has been cancelled
ubuntu / gcc-13 (push) Has been cancelled
ubuntu / gcc-14 (push) Has been cancelled
ubuntu / gcc-9 (push) Has been cancelled
windows / Visual Studio 2019 (push) Has been cancelled
windows / Visual Studio 2022 (push) Has been cancelled

This commit is contained in:
sha512sum 2024-10-19 23:02:24 +00:00
parent 6c8e87da57
commit ad4ba073a3
6 changed files with 599 additions and 351 deletions

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.30)
include(GNUInstallDirs) include(GNUInstallDirs)
@ -22,6 +22,7 @@ endif()
option(NAMEOF_OPT_BUILD_EXAMPLES "Build nameof examples" ${IS_TOPLEVEL_PROJECT}) option(NAMEOF_OPT_BUILD_EXAMPLES "Build nameof examples" ${IS_TOPLEVEL_PROJECT})
option(NAMEOF_OPT_BUILD_TESTS "Build and perform nameof tests" ${IS_TOPLEVEL_PROJECT}) option(NAMEOF_OPT_BUILD_TESTS "Build and perform nameof tests" ${IS_TOPLEVEL_PROJECT})
option(NAMEOF_OPT_INSTALL "Generate and install nameof target" ${IS_TOPLEVEL_PROJECT}) option(NAMEOF_OPT_INSTALL "Generate and install nameof target" ${IS_TOPLEVEL_PROJECT})
option(NAMEOF_MODULE "Build nameof module" OFF)
if(NAMEOF_OPT_BUILD_EXAMPLES) if(NAMEOF_OPT_BUILD_EXAMPLES)
add_subdirectory(example) add_subdirectory(example)
@ -36,14 +37,34 @@ include(CMakePackageConfigHelpers)
set(EXPORT_NAMESPACE "${PROJECT_NAME}::") set(EXPORT_NAMESPACE "${PROJECT_NAME}::")
add_library("${PROJECT_NAME}" INTERFACE)
add_library("${EXPORT_NAMESPACE}${PROJECT_NAME}" ALIAS "${PROJECT_NAME}")
set(INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/include") set(INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(${PROJECT_NAME} if(NAMEOF_MODULE)
set(CMAKE_CXX_EXTENSIONS OFF)
add_library(${PROJECT_NAME})
target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${INCLUDES}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_definitions(${PROJECT_NAME} PRIVATE NAMEOF_MODULE)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
target_sources(${PROJECT_NAME} PUBLIC FILE_SET nameofModules TYPE CXX_MODULES
FILES src/nameof.cpp)
else()
add_library("${PROJECT_NAME}" INTERFACE)
target_include_directories(${PROJECT_NAME}
INTERFACE INTERFACE
$<BUILD_INTERFACE:${INCLUDES}> $<BUILD_INTERFACE:${INCLUDES}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
endif()
add_library("${EXPORT_NAMESPACE}${PROJECT_NAME}" ALIAS "${PROJECT_NAME}")
if(NAMEOF_OPT_INSTALL) if(NAMEOF_OPT_INSTALL)
list(APPEND CMAKE_MODULE_PATH "${ADDITIONAL_MODULES_DIR}/GenPkgConfig") list(APPEND CMAKE_MODULE_PATH "${ADDITIONAL_MODULES_DIR}/GenPkgConfig")
@ -54,6 +75,10 @@ if(NAMEOF_OPT_INSTALL)
string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}") string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}")
install(TARGETS "${PROJECT_NAME}" install(TARGETS "${PROJECT_NAME}"
EXPORT ${PROJECT_NAME} EXPORT ${PROJECT_NAME}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
FILE_SET nameofModules DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES INCLUDES
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
# COMPONENT "${SDK_COMPONENT_NAME}" # component is not allowed for includes! Headers are installed separately! Includes only marks the headers for export # COMPONENT "${SDK_COMPONENT_NAME}" # component is not allowed for includes! Headers are installed separately! Includes only marks the headers for export

View file

@ -12,10 +12,12 @@ endif()
function(make_example target) function(make_example target)
add_executable(${target} ${target}.cpp) add_executable(${target} ${target}.cpp)
set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF) set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF)
target_compile_features(${target} PRIVATE cxx_std_17)
target_compile_options(${target} PRIVATE ${OPTIONS}) target_compile_options(${target} PRIVATE ${OPTIONS})
target_link_libraries(${target} PRIVATE ${CMAKE_PROJECT_NAME}) target_link_libraries(${target} PRIVATE ${CMAKE_PROJECT_NAME})
endfunction() endfunction()
make_example(example) make_example(example)
make_example(example_custom_name) make_example(example_custom_name)
if(NAMEOF_MODULE)
make_example(example_module)
endif()

View file

@ -0,0 +1,11 @@
import nameof;
#include <nameof_macro.hpp>
struct Test {};
auto main() -> int {
auto _ = nameof::nameof_type<Test>();
{
auto _ = NAMEOF_TYPE(Test);
}
}

File diff suppressed because it is too large Load diff

149
include/nameof_macro.hpp Normal file
View file

@ -0,0 +1,149 @@
#ifndef NEARGYE_NAMEOF_MACRO_HPP
#define NEARGYE_NAMEOF_MACRO_HPP
// Checks nameof_type compiler compatibility.
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 7 || defined(_MSC_VER) && _MSC_VER >= 1910
#undef NAMEOF_TYPE_SUPPORTED
#define NAMEOF_TYPE_SUPPORTED 1
#endif
// Checks nameof_type_rtti compiler compatibility.
#if defined(__clang__)
#if __has_feature(cxx_rtti)
#undef NAMEOF_TYPE_RTTI_SUPPORTED
#define NAMEOF_TYPE_RTTI_SUPPORTED 1
#endif
#elif defined(__GNUC__)
#if defined(__GXX_RTTI)
#undef NAMEOF_TYPE_RTTI_SUPPORTED
#define NAMEOF_TYPE_RTTI_SUPPORTED 1
#endif
#elif defined(_MSC_VER)
#if defined(_CPPRTTI)
#undef NAMEOF_TYPE_RTTI_SUPPORTED
#define NAMEOF_TYPE_RTTI_SUPPORTED 1
#endif
#endif
// Checks nameof_member compiler compatibility.
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 7 || \
defined(_MSC_VER) && defined(_MSVC_LANG) && _MSVC_LANG >= 202002L
#undef NAMEOF_MEMBER_SUPPORTED
#define NAMEOF_MEMBER_SUPPORTED 1
#endif
// Checks nameof_pointer compiler compatibility.
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 7 || \
defined(_MSC_VER) && defined(_MSVC_LANG) && _MSVC_LANG >= 202002L
#undef NAMEOF_POINTER_SUPPORTED
#define NAMEOF_POINTER_SUPPORTED 1
#endif
// Checks nameof_enum compiler compatibility.
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1910
#undef NAMEOF_ENUM_SUPPORTED
#define NAMEOF_ENUM_SUPPORTED 1
#endif
// Checks nameof_enum compiler aliases compatibility.
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1920
#undef NAMEOF_ENUM_SUPPORTED_ALIASES
#define NAMEOF_ENUM_SUPPORTED_ALIASES 1
#endif
// Enum value must be greater or equals than NAMEOF_ENUM_RANGE_MIN. By default NAMEOF_ENUM_RANGE_MIN = -128.
// If need another min range for all enum types by default, redefine the macro NAMEOF_ENUM_RANGE_MIN.
#if !defined(NAMEOF_ENUM_RANGE_MIN)
#define NAMEOF_ENUM_RANGE_MIN -128
#endif
// Enum value must be less or equals than NAMEOF_ENUM_RANGE_MAX. By default NAMEOF_ENUM_RANGE_MAX = 128.
// If need another max range for all enum types by default, redefine the macro NAMEOF_ENUM_RANGE_MAX.
#if !defined(NAMEOF_ENUM_RANGE_MAX)
#define NAMEOF_ENUM_RANGE_MAX 128
#endif
#define NAMEOF_VERSION_MAJOR 0
#define NAMEOF_VERSION_MINOR 10
#define NAMEOF_VERSION_PATCH 4
// Obtains name of variable, function, macro.
#define NAMEOF(...) \
[]() constexpr noexcept { \
::std::void_t<decltype(__VA_ARGS__)>(); \
constexpr auto _name = ::nameof::detail::pretty_name(#__VA_ARGS__); \
static_assert(!_name.empty(), "Expression does not have a name."); \
constexpr auto _size = _name.size(); \
constexpr auto _nameof = ::nameof::cstring<_size>{_name}; \
return _nameof; \
}()
// Obtains full name of variable, function, macro.
#define NAMEOF_FULL(...) \
[]() constexpr noexcept { \
::std::void_t<decltype(__VA_ARGS__)>(); \
constexpr auto _name = ::nameof::detail::pretty_name(#__VA_ARGS__, false); \
static_assert(!_name.empty(), "Expression does not have a name."); \
constexpr auto _size = _name.size(); \
constexpr auto _nameof_full = ::nameof::cstring<_size>{_name}; \
return _nameof_full; \
}()
// Obtains raw name of variable, function, macro.
#define NAMEOF_RAW(...) \
[]() constexpr noexcept { \
::std::void_t<decltype(__VA_ARGS__)>(); \
constexpr auto _name = ::nameof::string_view{#__VA_ARGS__}; \
static_assert(!_name.empty(), "Expression does not have a name."); \
constexpr auto _size = _name.size(); \
constexpr auto _nameof_raw = ::nameof::cstring<_size>{_name}; \
return _nameof_raw; \
}()
// Obtains name of enum variable.
#define NAMEOF_ENUM(...) ::nameof::nameof_enum<::std::decay_t<decltype(__VA_ARGS__)>>(__VA_ARGS__)
// Obtains name of enum variable or default value if enum variable out of range.
#define NAMEOF_ENUM_OR(...) ::nameof::nameof_enum_or(__VA_ARGS__)
// Obtains name of static storage enum variable.
// This version is much lighter on the compile times and is not restricted to the enum_range limitation.
#define NAMEOF_ENUM_CONST(...) ::nameof::nameof_enum<__VA_ARGS__>()
// Obtains name of enum-flags variable.
#define NAMEOF_ENUM_FLAG(...) ::nameof::nameof_enum_flag<::std::decay_t<decltype(__VA_ARGS__)>>(__VA_ARGS__)
// Obtains type name, reference and cv-qualifiers are ignored.
#define NAMEOF_TYPE(...) ::nameof::nameof_type<__VA_ARGS__>()
// Obtains full type name, with reference and cv-qualifiers.
#define NAMEOF_FULL_TYPE(...) ::nameof::nameof_full_type<__VA_ARGS__>()
// Obtains short type name.
#define NAMEOF_SHORT_TYPE(...) ::nameof::nameof_short_type<__VA_ARGS__>()
// Obtains type name of expression, reference and cv-qualifiers are ignored.
#define NAMEOF_TYPE_EXPR(...) ::nameof::nameof_type<decltype(__VA_ARGS__)>()
// Obtains full type name of expression, with reference and cv-qualifiers.
#define NAMEOF_FULL_TYPE_EXPR(...) ::nameof::nameof_full_type<decltype(__VA_ARGS__)>()
// Obtains short type name of expression.
#define NAMEOF_SHORT_TYPE_EXPR(...) ::nameof::nameof_short_type<decltype(__VA_ARGS__)>()
// Obtains type name, with reference and cv-qualifiers, using RTTI.
#define NAMEOF_TYPE_RTTI(...) ::nameof::detail::nameof_type_rtti<::std::void_t<decltype(__VA_ARGS__)>>(typeid(__VA_ARGS__).name())
// Obtains full type name, using RTTI.
#define NAMEOF_FULL_TYPE_RTTI(...) ::nameof::detail::nameof_full_type_rtti<decltype(__VA_ARGS__)>(typeid(__VA_ARGS__).name())
// Obtains short type name, using RTTI.
#define NAMEOF_SHORT_TYPE_RTTI(...) ::nameof::detail::nameof_short_type_rtti<decltype(__VA_ARGS__)>(typeid(__VA_ARGS__).name())
// Obtains name of member.
#define NAMEOF_MEMBER(...) ::nameof::nameof_member<__VA_ARGS__>()
// Obtains name of a function, a global or class static variable.
#define NAMEOF_POINTER(...) ::nameof::nameof_pointer<__VA_ARGS__>()
#endif

46
src/nameof.cpp Normal file
View file

@ -0,0 +1,46 @@
module;
#ifndef NAMEOF_IMPORT_STD
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <iterator>
#include <limits>
#include <type_traits>
#include <utility>
#if !defined(NAMEOF_USING_ALIAS_STRING)
#include <string>
#endif
#if !defined(NAMEOF_USING_ALIAS_STRING_VIEW)
#include <string_view>
#endif
#if __has_include(<cxxabi.h>)
#include <cxxabi.h>
#include <cstdlib>
#endif
#endif
export module nameof;
#ifdef NAMEOF_IMPORT_STD
import std;
#endif
#ifdef NAMEOF_ATTACH_TO_GLOBAL_MODULE
extern "C++" {
#endif
#include <nameof.hpp>
#ifdef NAMEOF_ATTACH_TO_GLOBAL_MODULE
} // extern "C++"
#endif