Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
61 changes: 59 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ jobs:
- toolset: clang
cxxstd: "11,14,17,20"
os: macos-13
- 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 @@ -70,6 +74,32 @@ jobs:
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--depth 10 --jobs 3" $LIBRARY
./bootstrap.sh
./b2 -j4 variant=debug tools/inspect
- name: Run modules tests wihtout 'import std;'


if: ${{matrix.toolset == 'clang-19'}}
run: |
cd ../boost-root/libs/lexical_cast
mkdir build_module
cd build_module
cmake -DBOOST_USE_MODULES=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/lexical_cast
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 CMake tests
if: ${{matrix.toolset == 'gcc-14'}}
Expand Down Expand Up @@ -173,8 +203,35 @@ jobs:
cmake -DBUILD_TESTING=1 -DBOOST_INCLUDE_LIBRARIES=lexical_cast ..
cmake --build . --target tests --config Debug
ctest --output-on-failure --no-tests=error -C Debug
cd ..
rm -rf __build

- name: Run modules tests
if: false
#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/lexical_cast
rm -rf build_module
mkdir build_module
cd build_module
cmake -DBOOST_USE_MODULES=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

- name: Run modules tests wihtout '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/lexical_cast
rm -rf build_module
mkdir build_module
cd build_module
cmake -DBOOST_USE_MODULES=1 -DCMAKE_CXX_STANDARD=20 -G Ninja ../test/cmake_subdir_test/
cmake --build .
ctest --no-tests=error -V

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

cmake_minimum_required(VERSION 3.5...3.16)
cmake_minimum_required(VERSION 3.5...4.0)

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

add_library(boost_lexical_cast INTERFACE)
add_library(Boost::lexical_cast ALIAS boost_lexical_cast)

target_include_directories(boost_lexical_cast INTERFACE include)
if (BOOST_USE_MODULES)
add_library(boost_lexical_cast)
target_sources(boost_lexical_cast PUBLIC
FILE_SET modules_public TYPE CXX_MODULES FILES
${CMAKE_CURRENT_LIST_DIR}/modules/boost_lexical_cast.cppm
)

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

target_include_directories(boost_lexical_cast ${__scope} include)
target_link_libraries(boost_lexical_cast
INTERFACE
${__scope}
Boost::config
Boost::container
Boost::core
Boost::throw_exception
)

add_library(Boost::lexical_cast ALIAS boost_lexical_cast)

if(BUILD_TESTING)
add_subdirectory(test)
endif()
Expand Down
37 changes: 37 additions & 0 deletions doc/lexical_cast.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,45 @@ limitation of compiler options that you use.

[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::lexical_cast` CMake target provide it. After that an explicit usage of C++20 module `boost.lexical_cast` is allowed:

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

The `Boost::lexical_cast` 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/lexical_cast...` includes implicitly do `import boost.lexical_cast;` to give all the
benefits of modules without changing the existing code.

[note For better compile times make sure that `import std;` is available when building the `boost.lexical_cast` 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/boost_lexical_cast.cppm` file.

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

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

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

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

[endsect]

[section Changes]

* [*boost 1.91.0 :]
* Added C++20 modules support.

* [*boost 1.86.0 :]

* Fixed conversion of `std::basic_string_view` and `boost::basic_string_view`
Expand Down
10 changes: 10 additions & 0 deletions include/boost/lexical_cast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
#ifndef BOOST_LEXICAL_CAST_INCLUDED
#define BOOST_LEXICAL_CAST_INCLUDED

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

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

#ifndef BOOST_LEXICAL_CAST_INTERFACE_UNIT
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#endif

#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
Expand All @@ -34,6 +40,7 @@

namespace boost
{
BOOST_LEXICAL_CAST_BEGIN_MODULE_EXPORT
template <typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
Expand Down Expand Up @@ -94,9 +101,12 @@ namespace boost
);
}

BOOST_LEXICAL_CAST_END_MODULE_EXPORT
} // namespace boost

#undef BOOST_LCAST_NO_WCHAR_T

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

#endif // BOOST_LEXICAL_CAST_INCLUDED

10 changes: 10 additions & 0 deletions include/boost/lexical_cast/bad_lexical_cast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
#ifndef BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP
#define BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP

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

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

#ifndef BOOST_LEXICAL_CAST_INTERFACE_UNIT
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
Expand All @@ -26,9 +31,11 @@
#include <exception>
#include <typeinfo>
#include <boost/throw_exception.hpp>
#endif

namespace boost
{
BOOST_LEXICAL_CAST_BEGIN_MODULE_EXPORT
// exception used to indicate runtime lexical_cast failure
class BOOST_SYMBOL_VISIBLE bad_lexical_cast :
// workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
Expand Down Expand Up @@ -80,6 +87,7 @@ namespace boost
const type_info_t *target;
#endif
};
BOOST_LEXICAL_CAST_END_MODULE_EXPORT

namespace conversion { namespace detail {
#ifdef BOOST_NO_TYPEID
Expand All @@ -97,4 +105,6 @@ namespace boost

} // namespace boost

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

#endif // BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP
8 changes: 8 additions & 0 deletions include/boost/lexical_cast/detail/buffer_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@
#ifndef BOOST_LEXICAL_CAST_DETAIL_BUFFER_VIEW_HPP
#define BOOST_LEXICAL_CAST_DETAIL_BUFFER_VIEW_HPP

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

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

#ifndef BOOST_LEXICAL_CAST_INTERFACE_UNIT
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif

#include <iosfwd>
#endif

namespace boost { namespace conversion { namespace detail {

Expand Down Expand Up @@ -55,5 +61,7 @@ namespace boost { namespace conversion { namespace detail {

}}} // namespace boost::conversion::detail

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

#endif // BOOST_LEXICAL_CAST_DETAIL_BUFFER_VIEW_HPP

22 changes: 22 additions & 0 deletions include/boost/lexical_cast/detail/config.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright Antony Polukhin, 2021-2025.
//
// 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_LEXICAL_CAST_DETAIL_CONFIG_HPP
#define BOOST_LEXICAL_CAST_DETAIL_CONFIG_HPP

#ifdef BOOST_LEXICAL_CAST_INTERFACE_UNIT
# define BOOST_LEXICAL_CAST_BEGIN_MODULE_EXPORT export {
# define BOOST_LEXICAL_CAST_END_MODULE_EXPORT }
#else
# define BOOST_LEXICAL_CAST_BEGIN_MODULE_EXPORT
# define BOOST_LEXICAL_CAST_END_MODULE_EXPORT
#endif

#if defined(BOOST_USE_MODULES) && !defined(BOOST_LEXICAL_CAST_INTERFACE_UNIT)
import boost.lexical_cast;
#endif

#endif // #ifndef BOOST_LEXICAL_CAST_DETAIL_CONFIG_HPP
20 changes: 14 additions & 6 deletions include/boost/lexical_cast/detail/converter_lexical.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
#ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
#define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP

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

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

#ifndef BOOST_LEXICAL_CAST_INTERFACE_UNIT
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
Expand All @@ -27,25 +32,26 @@
#define BOOST_LCAST_NO_WCHAR_T
#endif

#include <array>
#include <cstddef>
#include <string>
#include <type_traits>
#include <boost/limits.hpp>
#include <boost/detail/lcast_precision.hpp>

#include <boost/lexical_cast/detail/widest_char.hpp>
#include <boost/lexical_cast/detail/is_character.hpp>
#include <boost/lexical_cast/detail/type_traits.hpp>

#include <array>

#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
#include <string_view>
#endif

#include <boost/lexical_cast/detail/buffer_view.hpp>
#include <boost/container/container_fwd.hpp>

#endif // #ifndef BOOST_LEXICAL_CAST_INTERFACE_UNIT

#include <boost/lexical_cast/detail/lcast_precision.hpp>
#include <boost/lexical_cast/detail/widest_char.hpp>
#include <boost/lexical_cast/detail/is_character.hpp>
#include <boost/lexical_cast/detail/buffer_view.hpp>
#include <boost/lexical_cast/detail/converter_lexical_streams.hpp>

namespace boost {
Expand Down Expand Up @@ -479,5 +485,7 @@ namespace boost {

#undef BOOST_LCAST_NO_WCHAR_T

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

#endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP

Loading