Skip to content

Commit dc78cf1

Browse files
authored
Implement initial version of C++20 module boost.type_index (#15)
`#include <boost/type_index...` is now implicitly does `import boost.type_index` if the modules are supported All the library internals now have unconditional module level linkage. Significant differences from https://anarthal.github.io/cppblog/modules3: * `BOOST_TYPE_INDEX_USE_STD_MODULE` macro switch for `import std;` / `includes` while building module. This allows to use module in C++20 and even without usable `std` module.
1 parent 14ee258 commit dc78cf1

26 files changed

+468
-42
lines changed

.github/workflows/ci.yml

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ jobs:
4949
compiler: clang++-14
5050
cxxstd: "03,11,14,17,2a"
5151
os: ubuntu-22.04
52-
- toolset: clang
53-
compiler: clang++-10
54-
cxxstd: "03,11,14,17,2a"
55-
os: ubuntu-20.04
52+
- toolset: clang-19
53+
cxxstd: "20,23"
54+
os: ubuntu-24.04
55+
install: clang-19 llvm-19 libclang-rt-19-dev libc++-19-dev libc++abi-19-dev clang-tools-19
5656

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

@@ -88,6 +88,31 @@ jobs:
8888
./b2 -d0 headers
8989
./b2 -j4 variant=debug tools/inspect/build
9090
91+
- name: Run modules tests wihtout 'import std;'
92+
if: ${{matrix.toolset == 'clang-19'}}
93+
run: |
94+
cd ../boost-root/libs/type_index
95+
mkdir build_module
96+
cd build_module
97+
cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -GNinja -DCMAKE_CXX_COMPILER=clang++-19 ../test/cmake_subdir_test/
98+
cmake --build .
99+
ctest -V
100+
cd ..
101+
rm -rf build_module
102+
103+
- name: Run modules tests
104+
if: false
105+
#if: ${{matrix.toolset == 'clang-19'}}
106+
run: |
107+
cd ../boost-root/libs/type_index
108+
mkdir build_module
109+
cd build_module
110+
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/
111+
cmake --build .
112+
ctest -V
113+
cd ..
114+
rm -rf build_module
115+
91116
- name: Run tests
92117
run: |
93118
cd ../boost-root
@@ -175,6 +200,36 @@ jobs:
175200
cmd /c bootstrap
176201
b2 -d0 headers
177202
203+
- name: Run modules tests
204+
if: ${{matrix.toolset == 'msvc-14.3'}}
205+
shell: cmd
206+
run: |
207+
choco install --no-progress ninja
208+
call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64
209+
cd ../boost-root/libs/type_index
210+
mkdir build_module
211+
cd build_module
212+
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/
213+
cmake --build .
214+
ctest --no-tests=error -V
215+
cd ..
216+
rm -rf build_module
217+
218+
- name: Run modules tests without 'import std;'
219+
if: ${{matrix.toolset == 'msvc-14.3'}}
220+
shell: cmd
221+
run: |
222+
choco install --no-progress ninja
223+
call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" x64
224+
cd ../boost-root/libs/type_index
225+
mkdir build_module
226+
cd build_module
227+
cmake -DBOOST_USE_MODULES=1 -DBUILD_TESTING=1 -DCMAKE_CXX_STANDARD=20 -G Ninja ../test/cmake_subdir_test/
228+
cmake --build .
229+
ctest --no-tests=error -V
230+
cd ..
231+
rm -rf build_module
232+
178233
- name: Run tests
179234
shell: cmd
180235
run: |

CMakeLists.txt

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,35 @@
33
# Distributed under the Boost Software License, Version 1.0.
44
# https://www.boost.org/LICENSE_1_0.txt
55

6-
cmake_minimum_required(VERSION 3.5...3.20)
6+
cmake_minimum_required(VERSION 3.5...3.31)
77

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

10-
add_library(boost_type_index INTERFACE)
11-
add_library(Boost::type_index ALIAS boost_type_index)
10+
if (BOOST_USE_MODULES)
11+
add_library(boost_type_index)
12+
target_sources(boost_type_index PUBLIC
13+
FILE_SET modules_public TYPE CXX_MODULES FILES modules/boost_type_index.cppm
14+
)
15+
16+
target_compile_features(boost_type_index PUBLIC cxx_std_20)
17+
target_compile_definitions(boost_type_index PUBLIC BOOST_USE_MODULES)
18+
if (CMAKE_CXX_COMPILER_IMPORT_STD)
19+
target_compile_definitions(boost_type_index PRIVATE BOOST_TYPE_INDEX_USE_STD_MODULE)
20+
message(STATUS "Using `import std;`")
21+
else()
22+
message(STATUS "`import std;` is not awailable")
23+
endif()
24+
set(__scope PUBLIC)
25+
else()
26+
add_library(boost_type_index INTERFACE)
27+
set(__scope INTERFACE)
28+
endif()
1229

13-
target_include_directories(boost_type_index INTERFACE include)
30+
target_include_directories(boost_type_index ${__scope} include)
31+
add_library(Boost::type_index ALIAS boost_type_index)
1432

1533
target_link_libraries(boost_type_index
16-
INTERFACE
34+
${__scope}
1735
Boost::config
1836
Boost::container_hash
1937
Boost::core

doc/type_index.qbk

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[library Boost.TypeIndex
22
[quickbook 1.6]
3-
[version 4.1]
3+
[version 4.2]
44
[copyright 2012-2025 Antony Polukhin]
55
[category Language Features Emulation]
66
[license
@@ -314,6 +314,40 @@ Sometimes there may be a need to create your own type info system. This may be u
314314

315315
[endsect]
316316

317+
[section C++20 module]
318+
319+
[caution C++20 module support is on early stage, targets, flags and behavior may change in the future]
320+
321+
If using modern CMake define CMake option `-DBOOST_USE_MODULES=1` to build a C++20 module and
322+
make the `Boost::type_index` CMake target provide it. After that an explicit usage of C++20 module `boost.type_index` is allowed:
323+
324+
[import ../modules/usage_sample.cpp]
325+
[type_index_module_example]
326+
327+
The `Boost::type_index` CMake target gives an ability to mix includes and imports of the library in different translation units. Moreover,
328+
if `BOOST_USE_MODULES` macro is defined then all the `boost/type_index/...` includes implicilty do `import boost.type_index;` to give all the
329+
benifits of modules without changing the existing code.
330+
331+
[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
332+
a 'Using `import std;`' message). ]
333+
334+
If not using CMake, then the module could be build manually from the `modules/boost_type_index.cppm` file.
335+
336+
For manual module build the following commands can be used for clang compiler:
337+
338+
```
339+
cd type_index/modules
340+
clang++ -I ../include -std=c++20 --precompile -x c++-module boost_type_index.cppm
341+
```
342+
343+
After that, the module could be used in the following way:
344+
345+
```
346+
clang++ -std=c++20 -fmodule-file=boost_type_index.pcm boost_type_index.pcm usage_sample.cpp
347+
```
348+
349+
[endsect]
350+
317351

318352
[section Space and Performance]
319353

include/boost/type_index.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
/// By inclusion of this file most optimal type index classes will be included and used
1515
/// as a boost::typeindex::type_index and boost::typeindex::type_info.
1616

17-
#include <boost/config.hpp>
17+
#include <boost/type_index/detail/config.hpp>
1818

1919
#ifdef BOOST_HAS_PRAGMA_ONCE
2020
# pragma once
@@ -49,8 +49,12 @@
4949
#define BOOST_TYPE_INDEX_REGISTER_CLASS
5050
#endif
5151

52+
#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
53+
5254
namespace boost { namespace typeindex {
5355

56+
BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT
57+
5458
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
5559

5660
/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
@@ -257,9 +261,11 @@ inline type_index type_id_runtime(const T& runtime_val) noexcept {
257261
return type_index::type_id_runtime(runtime_val);
258262
}
259263

260-
}} // namespace boost::typeindex
264+
BOOST_TYPE_INDEX_END_MODULE_EXPORT
261265

266+
}} // namespace boost::typeindex
262267

268+
#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
263269

264270
#endif // BOOST_TYPE_INDEX_HPP
265271

include/boost/type_index/ctti_type_index.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,19 @@
1818
/// It is used in situations when typeid() method is not available or
1919
/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined.
2020

21+
#include <boost/type_index/detail/config.hpp>
22+
23+
#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
24+
2125
#include <boost/type_index/type_index_facade.hpp>
2226
#include <boost/type_index/detail/compile_time_type_info.hpp>
2327

28+
#if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
2429
#include <cstring>
2530
#include <type_traits>
31+
2632
#include <boost/container_hash/hash.hpp>
33+
#endif
2734

2835
#ifdef BOOST_HAS_PRAGMA_ONCE
2936
# pragma once
@@ -64,6 +71,8 @@ class ctti_data {
6471

6572
} // namespace detail
6673

74+
BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT
75+
6776
/// Helper method for getting detail::ctti_data of a template parameter T.
6877
template <class T>
6978
inline const detail::ctti_data& ctti_construct() noexcept {
@@ -132,6 +141,8 @@ class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_da
132141
inline static ctti_type_index type_id_runtime(const T& variable) noexcept;
133142
};
134143

144+
BOOST_TYPE_INDEX_END_MODULE_EXPORT
145+
135146

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

200-
201211
}} // namespace boost::typeindex
202212

213+
#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
214+
203215
#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
204216

include/boost/type_index/detail/compile_time_type_info.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index.
1414
/// Not intended for inclusion from user's code.
1515

16-
#include <boost/config.hpp>
16+
#include <boost/type_index/detail/config.hpp>
1717

18+
#if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
1819
#include <cstring>
1920
#include <type_traits>
21+
#endif
2022

2123
#ifdef BOOST_HAS_PRAGMA_ONCE
2224
# pragma once
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// Copyright 2013-2025 Antony Polukhin.
3+
//
4+
//
5+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7+
//
8+
9+
#ifndef BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP
10+
#define BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP
11+
12+
#if !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
13+
#include <boost/config.hpp>
14+
#ifdef BOOST_HAS_PRAGMA_ONCE
15+
# pragma once
16+
#endif
17+
#endif
18+
19+
#ifdef BOOST_TYPE_INDEX_INTERFACE_UNIT
20+
# define BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT export {
21+
# define BOOST_TYPE_INDEX_END_MODULE_EXPORT }
22+
#else
23+
# define BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT
24+
# define BOOST_TYPE_INDEX_END_MODULE_EXPORT
25+
#endif
26+
27+
#if defined(BOOST_USE_MODULES) && !defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
28+
import boost.type_index;
29+
#endif
30+
31+
#endif // BOOST_TYPE_INDEX_DETAIL_CONFIG_HPP
32+

include/boost/type_index/detail/ctti_register_class.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,23 @@
1919
# pragma once
2020
#endif
2121

22+
#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
23+
2224
namespace boost { namespace typeindex { namespace detail {
2325

26+
BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT
27+
2428
template <class T>
2529
inline const ctti_data& ctti_construct_typeid_ref(const T*) noexcept {
2630
return boost::typeindex::ctti_construct<T>();
2731
}
2832

33+
BOOST_TYPE_INDEX_END_MODULE_EXPORT
34+
2935
}}} // namespace boost::typeindex::detail
3036

37+
#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
38+
3139
/// @cond
3240
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
3341
virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const noexcept { \

include/boost/type_index/detail/stl_register_class.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,23 @@
1919
# pragma once
2020
#endif
2121

22+
#if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
23+
2224
namespace boost { namespace typeindex { namespace detail {
2325

26+
BOOST_TYPE_INDEX_BEGIN_MODULE_EXPORT
27+
2428
template <class T>
2529
inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) noexcept {
2630
return typeid(T);
2731
}
2832

33+
BOOST_TYPE_INDEX_END_MODULE_EXPORT
34+
2935
}}} // namespace boost::typeindex::detail
3036

37+
#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_TYPE_INDEX_INTERFACE_UNIT)
38+
3139
/// @cond
3240
#define BOOST_TYPE_INDEX_REGISTER_CLASS \
3341
virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const noexcept { \

include/boost/type_index/runtime_cast.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_HPP
1010
#define BOOST_TYPE_INDEX_RUNTIME_CAST_HPP
1111

12+
#include <boost/type_index/detail/config.hpp>
13+
1214
/// \file runtime_cast.hpp
1315
/// \brief Contains the basic utilities necessary to fully emulate
1416
/// dynamic_cast for language level constructs (raw pointers and references).

0 commit comments

Comments
 (0)