Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 59 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ jobs:
compiler: clang++-14
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: clang-19
cxxstd: "20,23"
os: ubuntu-24.04
install: clang-19 llvm-19 libclang-rt-19-dev libc++-19-dev libc++abi-19-dev clang-tools-19

runs-on: ${{matrix.os}}

Expand Down Expand Up @@ -88,6 +88,31 @@ jobs:
./b2 -d0 headers
./b2 -j4 variant=debug tools/inspect/build

- name: Run modules tests wihtout 'import std;'
if: ${{matrix.toolset == 'clang-19'}}
run: |
cd ../boost-root/libs/type_index
mkdir build_module
cd build_module
cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -GNinja -DCMAKE_CXX_COMPILER=clang++-19 ../test/cmake_subdir_test/
cmake --build .
ctest -V
cd ..
rm -rf build_module

- name: Run modules tests
if: false
#if: ${{matrix.toolset == 'clang-19'}}
run: |
cd ../boost-root/libs/type_index
mkdir build_module
cd build_module
cmake -DBUILD_TESTING=1 -DBOOST_USE_MODULES=1 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_CXX_FLAGS=-stdlib=libc++ -DCMAKE_EXE_LINKER_FLAGS=-stdlib=libc++ -DCMAKE_CXX_STANDARD=23 -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=0e5b6991-d74f-4b3d-a41c-cf096e0b2508 -G Ninja ../test/cmake_subdir_test/
cmake --build .
ctest -V
cd ..
rm -rf build_module

- name: Run tests
run: |
cd ../boost-root
Expand Down Expand Up @@ -175,6 +200,36 @@ jobs:
cmd /c bootstrap
b2 -d0 headers

- name: Run modules tests
if: ${{matrix.toolset == 'msvc-14.3'}}
shell: cmd
run: |
choco install --no-progress ninja
call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64
cd ../boost-root/libs/type_index
mkdir build_module
cd build_module
cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -DCMAKE_CXX_STANDARD=23 -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=0e5b6991-d74f-4b3d-a41c-cf096e0b2508 -G Ninja ../test/cmake_subdir_test/
cmake --build .
ctest --no-tests=error -V
cd ..
rm -rf build_module

- name: Run modules tests without 'import std;'
if: ${{matrix.toolset == 'msvc-14.3'}}
shell: cmd
run: |
choco install --no-progress ninja
call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64
cd ../boost-root/libs/type_index
mkdir build_module
cd build_module
cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -DCMAKE_CXX_STANDARD=20 -G Ninja ../test/cmake_subdir_test/
cmake --build .
ctest --no-tests=error -V
cd ..
rm -rf build_module

- name: Run tests
shell: cmd
run: |
Expand Down
29 changes: 24 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,36 @@
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt

cmake_minimum_required(VERSION 3.5...3.20)
cmake_minimum_required(VERSION 3.5...3.31)

project(boost_type_index VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)

add_library(boost_type_index INTERFACE)
add_library(Boost::type_index ALIAS boost_type_index)
if (BOOST_USE_MODULES)
add_library(boost_type_index)
target_sources(boost_type_index PUBLIC
FILE_SET modules_public TYPE CXX_MODULES FILES
${CMAKE_CURRENT_LIST_DIR}/modules/type_index.cppm

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convention is boost_type_index.cppm

)

target_compile_features(boost_type_index PUBLIC cxx_std_20)
target_compile_definitions(boost_type_index PUBLIC BOOST_USE_MODULES)
if (CMAKE_CXX_COMPILER_IMPORT_STD)
target_compile_definitions(boost_type_index PRIVATE BOOST_TYPE_INDEX_USE_STD_MODULE)
message(STATUS "Using `import std;`")
else()
message(STATUS "`import std;` is not awailable")
endif()
set(__scope PUBLIC)
else()
add_library(boost_type_index INTERFACE)
set(__scope INTERFACE)
endif()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I missing something or is there no ${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt? I'd advise to remove this check if you know for sure that the file should be present. AFAIK this is generated by Peter's CMake generator so it's compatible with libraries that don't run their tests via CMake.

target_include_directories(boost_type_index INTERFACE include)
target_include_directories(boost_type_index ${__scope} include)
add_library(Boost::type_index ALIAS boost_type_index)

target_link_libraries(boost_type_index
INTERFACE
${__scope}
Boost::config
Boost::container_hash
Boost::core
Expand Down
36 changes: 35 additions & 1 deletion doc/type_index.qbk
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[library Boost.TypeIndex
[quickbook 1.6]
[version 4.1]
[version 4.2]
[copyright 2012-2025 Antony Polukhin]
[category Language Features Emulation]
[license
Expand Down Expand Up @@ -314,6 +314,40 @@ Sometimes there may be a need to create your own type info system. This may be u

[endsect]

[section C++20 module]

[caution C++20 module support is on early stage, targets, flags and behavior may change in the future]

If using modern CMake define CMake option `-DBOOST_USE_MODULES=1` to build a C++20 module and
make the `Boost::type_index` CMake target provide it. After that an explicit usage of C++20 module `boost.type_index` is allowed:

[import ../modules/usage_sample.cpp]
[type_index_module_example]

The `Boost::type_index` CMake target gives an ability to mix includes and imports of the library in different translation units. Moreover,
if `BOOST_USE_MODULES` macro is defined then all the `boost/type_index/...` includes implicilty do `import boost.type_index;` to give all the
benifits of modules without changing the existing code.

[note For better compile times make sure that `import std;` is available when building the `boost.type_index` module (in CMake logs there should be
a 'Using `import std;`' message). ]

If not using CMake, then the module could be build manually from the `modules/type_index.cppm` file.

For manual module build the following commands could be used for clang compiler:

```
cd type_index/modules
clang++ -I ../include -std=c++20 --precompile -x c++-module type_index.cppm
```

After that, the module could be used in the following way:

```
clang++ -std=c++20 -fmodule-file=type_index.pcm type_index.pcm usage_sample.cpp
```

[endsect]


[section Space and Performance]

Expand Down
10 changes: 9 additions & 1 deletion include/boost/type_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
/// By inclusion of this file most optimal type index classes will be included and used
/// as a boost::typeindex::type_index and boost::typeindex::type_info.

#include <boost/type_index/detail/config.hpp>

#include <boost/config.hpp>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're including this in the purview, you need to ifdef this include out.


#ifdef BOOST_HAS_PRAGMA_ONCE
Expand Down Expand Up @@ -49,8 +51,12 @@
#define BOOST_TYPE_INDEX_REGISTER_CLASS
#endif

#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

namespace boost { namespace typeindex {

BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT

#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)

/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are macros like BOOST_TYPE_INDEX_FUNCTION_SIGNATURE supposed to be public and available to the user? If the answer is yes, as you have written it here they won't be available in modular builds.

Expand Down Expand Up @@ -257,9 +263,11 @@ inline type_index type_id_runtime(const T& runtime_val) noexcept {
return type_index::type_id_runtime(runtime_val);
}

}} // namespace boost::typeindex
BOOST_TYPE_INDEX_END_MODULE_EXPORT

}} // namespace boost::typeindex

#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

#endif // BOOST_TYPE_INDEX_HPP

14 changes: 13 additions & 1 deletion include/boost/type_index/ctti_type_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@
/// It is used in situations when typeid() method is not available or
/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined.

#include <boost/type_index/detail/config.hpp>

#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

#include <boost/type_index/type_index_facade.hpp>
#include <boost/type_index/detail/compile_time_type_info.hpp>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file has STL headers that are not ifdef'ed out.


#if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
#include <cstring>
#include <type_traits>
#endif

#include <boost/container_hash/hash.hpp>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to ifdef-out other Boost headers, too.


#ifdef BOOST_HAS_PRAGMA_ONCE
Expand Down Expand Up @@ -64,6 +71,8 @@ class ctti_data {

} // namespace detail

BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT

/// Helper method for getting detail::ctti_data of a template parameter T.
template <class T>
inline const detail::ctti_data& ctti_construct() noexcept {
Expand Down Expand Up @@ -132,6 +141,8 @@ class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_da
inline static ctti_type_index type_id_runtime(const T& variable) noexcept;
};

BOOST_TYPE_INDEX_END_MODULE_EXPORT


inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const noexcept {
return *reinterpret_cast<const detail::ctti_data*>(data_);
Expand Down Expand Up @@ -197,8 +208,9 @@ inline std::size_t ctti_type_index::hash_code() const noexcept {
return boost::hash_range(raw_name(), raw_name() + get_raw_name_length());
}


}} // namespace boost::typeindex

#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP

25 changes: 25 additions & 0 deletions include/boost/type_index/detail/config.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Copyright 2013-2025 Antony Polukhin.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP
#define BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP

#ifdef BOOST_TYPE_INDEX_INTERFACE_UNIT
# define BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT export {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since export namespace boost { ... } works, too, you might simplify this to #define BOOST_TYPE_INDEX_EXPORT export when modules are enabled, and then just stick BOOST_TYPE_INDEX_EXPORT in front of your namespace declaration.

# define BOOST_TYPE_INDEX_END_MODULE_EXPORT }
#else
# define BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT
# define BOOST_TYPE_INDEX_END_MODULE_EXPORT
#endif

#if defined(BOOST_USE_MODULES) && !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
import boost.type_index;
#endif

#endif // BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP

8 changes: 8 additions & 0 deletions include/boost/type_index/detail/ctti_register_class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@
# pragma once
#endif

#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

namespace boost { namespace typeindex { namespace detail {

BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT

template <class T>
inline const ctti_data& ctti_construct_typeid_ref(const T*) noexcept {
return boost::typeindex::ctti_construct<T>();
}

BOOST_TYPE_INDEX_END_MODULE_EXPORT

}}} // namespace boost::typeindex::detail

#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

/// @cond
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const noexcept { \
Expand Down
8 changes: 8 additions & 0 deletions include/boost/type_index/detail/stl_register_class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@
# pragma once
#endif

#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

namespace boost { namespace typeindex { namespace detail {

BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT

template <class T>
inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) noexcept {
return typeid(T);
}

BOOST_TYPE_INDEX_END_MODULE_EXPORT

}}} // namespace boost::typeindex::detail

#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

/// @cond
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const noexcept { \
Expand Down
26 changes: 17 additions & 9 deletions include/boost/type_index/runtime_cast/boost_shared_ptr_cast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,25 @@
/// \brief Contains the overload of boost::typeindex::runtime_pointer_cast for
/// boost::shared_ptr types.

#include <boost/type_index/detail/config.hpp>

#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

#include <boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp>

#if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
#include <type_traits>
#endif

#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif

namespace boost {
template<class T> class shared_ptr;
}

namespace boost { namespace typeindex {

/// \brief Creates a new instance of std::shared_ptr whose stored pointer is obtained from u's
BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT

/// \brief Creates a new instance of smart pointer whose stored pointer is obtained from u's
/// stored pointer using a runtime_cast.
///
/// The new shared_ptr will share ownership with u, except that it is empty if the runtime_cast
Expand All @@ -37,14 +41,18 @@ namespace boost { namespace typeindex {
/// \return If there exists a valid conversion from U* to T*, returns a boost::shared_ptr<T>
/// that points to an address suitably offset from u.
/// If no such conversion exists, returns boost::shared_ptr<T>();
template<typename T, typename U>
boost::shared_ptr<T> runtime_pointer_cast(boost::shared_ptr<U> const& u) {
template<typename T, typename U, template <class> class SmartPointer>
auto runtime_pointer_cast(SmartPointer<U> const& u) -> decltype(u.use_count(), SmartPointer<T>()) {
T* value = detail::runtime_cast_impl<T>(u.get(), std::is_base_of<T, U>());
if(value)
return boost::shared_ptr<T>(u, value);
return boost::shared_ptr<T>();
return SmartPointer<T>(u, value);
return SmartPointer<T>();
}

BOOST_TYPE_INDEX_END_MODULE_EXPORT

}} // namespace boost::typeindex

#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)

#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_BOOST_SHARED_PTR_CAST_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

#include <boost/type_index.hpp>

#if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
#include <type_traits>
#endif

#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
Expand Down
Loading