Skip to content
Merged
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
30 changes: 30 additions & 0 deletions .github/workflows/cpm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CPM

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:

jobs:
test-cpm:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential wget g++-14

- name: Run CPM test
run: |
export CC=gcc-14
export CXX=g++-14
cd tests/cpm
chmod +x test_cpm.sh
./test_cpm.sh
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
/tests/benchmarks/NamedType
/tests/benchmarks/compile-time
/tests/benchmarks/results.md
/tests/cpm/build/
tests/cpm/cmake/
tests/cpm/CMakeLists.txt
CMakeUserPresets.json
includes/version.hpp
248 changes: 132 additions & 116 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,138 +1,154 @@
cmake_minimum_required(VERSION 3.31)
project(cpp_strong_type)

set(CMAKE_CXX_STANDARD 23)

if (MSVC)
set(WARNING_FLAGS
/W4
/WX
/permissive-
/Zc:__cplusplus
)
else ()
set(WARNING_FLAGS
-Wall
-Wextra
-Wpedantic
-Werror
-Wshadow
-Wnon-virtual-dtor
-Wold-style-cast
-Wcast-align
-Wunused
-Woverloaded-virtual
-Wpedantic
-Wconversion
-Wsign-conversion
-Wnull-dereference
-Wdouble-promotion
-Wformat=2
-Wimplicit-fallthrough
)

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
list(APPEND WARNING_FLAGS
-Wmisleading-indentation
-Wduplicated-cond
-Wduplicated-branches
-Wlogical-op
-Wuseless-cast
)
endif ()

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
list(APPEND WARNING_FLAGS
-Wc++23-compat
-Wmost
)
endif ()
endif ()

add_compile_options(${WARNING_FLAGS})
find_package(Catch2 3 REQUIRED)

# Create version.hpp ___________________________________________________________________________________________________

add_custom_target(create_version_hpp
COMMAND ${CMAKE_COMMAND} -E env python3 ./version.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} -E env python3 ${CMAKE_CURRENT_SOURCE_DIR}/version.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating version.hpp"
)

# Create single header library _________________________________________________________________________________________

add_custom_target(make_header_only
COMMAND ${CMAKE_COMMAND} -E env python3 ./make-header-only.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} -E env python3 ${CMAKE_CURRENT_SOURCE_DIR}/make-header-only.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating header-only library"
)

add_dependencies(make_header_only create_version_hpp)

# Unit-tests target with Catch2 _______________________________________________________________________________________

enable_testing()

# set include path in a variable
set(HEADERS_PATH ${CMAKE_SOURCE_DIR}/public)

add_executable(stronger_cpp_tests
tests/test_link/common.cpp
tests/test_link/api1.cpp
tests/test_declaration_macros.cpp
tests/test_arithmetic.cpp
tests/helpers.h
tests/mock_type.hpp
tests/test_operation_bindings.cpp
tests/test_bool.cpp
tests/test_types.cpp
tests/test_strength.cpp
tests/test_link.cpp
tests/test_data_accessors.cpp
includes/tag.hpp
tests/test_tag.cpp
tests/test_iterable.cpp
tests/runtime_tests.cpp
tests/test_sizes.cpp
tests/test_make_strong.cpp
includes/concepts/other_operators.hpp
tests/test_options.cpp
tests/test_version.cpp
)
target_compile_definitions(stronger_cpp_tests
PRIVATE
STRONGER_CPP_BUILD_TESTS
)
add_dependencies(stronger_cpp_tests make_header_only)
target_include_directories(stronger_cpp_tests
PRIVATE
${HEADERS_PATH}
)
target_link_libraries(stronger_cpp_tests
PRIVATE
Catch2::Catch2WithMain
# Library target for CPM consumers _____________________________________________________________________________________

add_library(stronger-cpp INTERFACE)
add_library(stronger-cpp::stronger-cpp ALIAS stronger-cpp)
add_dependencies(stronger-cpp make_header_only)
target_include_directories(stronger-cpp
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public>
)
target_compile_features(stronger-cpp INTERFACE cxx_std_23)

# Download NamedType for benchmarks ____________________________________________________________________________________
# Local targets ________________________________________________________________________________________________________

add_custom_target(download_NamedType
COMMAND ${CMAKE_COMMAND} -E env python3 ./tests/benchmarks/get-NamedType.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Getting NamedType library for benchmarks"
)
if (PROJECT_IS_TOP_LEVEL)
set(CMAKE_CXX_STANDARD 23)

if (MSVC)
set(WARNING_FLAGS
/W4
/WX
/permissive-
/Zc:__cplusplus
)
else ()
set(WARNING_FLAGS
-Wall
-Wextra
-Wpedantic
-Werror
-Wshadow
-Wnon-virtual-dtor
-Wold-style-cast
-Wcast-align
-Wunused
-Woverloaded-virtual
-Wpedantic
-Wconversion
-Wsign-conversion
-Wnull-dereference
-Wdouble-promotion
-Wformat=2
-Wimplicit-fallthrough
)

# Runtime benchmarks ___________________________________________________________________________________________________
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
list(APPEND WARNING_FLAGS
-Wmisleading-indentation
-Wduplicated-cond
-Wduplicated-branches
-Wlogical-op
-Wuseless-cast
)
endif ()

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
list(APPEND WARNING_FLAGS
-Wc++23-compat
-Wmost
)
endif ()
endif ()

add_executable(stronger_cpp_benchmarks
tests/benchmarks/benchmarks.cpp
)
add_dependencies(stronger_cpp_benchmarks make_header_only download_NamedType)
target_include_directories(stronger_cpp_benchmarks
PRIVATE
${HEADERS_PATH}
)
target_link_libraries(stronger_cpp_benchmarks
PRIVATE
Catch2::Catch2WithMain
)
add_compile_options(${WARNING_FLAGS})

# Unit-tests target with Catch2 _______________________________________________________________________________________

find_package(Catch2 3 REQUIRED)
enable_testing()

# set include path in a variable
set(HEADERS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/includes)

add_executable(stronger_cpp_tests
tests/test_link/common.cpp
tests/test_link/api1.cpp
tests/test_declaration_macros.cpp
tests/test_arithmetic.cpp
tests/helpers.h
tests/mock_type.hpp
tests/test_operation_bindings.cpp
tests/test_bool.cpp
tests/test_types.cpp
tests/test_strength.cpp
tests/test_link.cpp
tests/test_data_accessors.cpp
includes/tag.hpp
tests/test_tag.cpp
tests/test_iterable.cpp
tests/runtime_tests.cpp
tests/test_sizes.cpp
tests/test_make_strong.cpp
includes/concepts/other_operators.hpp
tests/test_options.cpp
tests/test_version.cpp
)
target_compile_definitions(stronger_cpp_tests
PRIVATE
STRONGER_CPP_BUILD_TESTS
)
add_dependencies(stronger_cpp_tests make_header_only)
target_include_directories(stronger_cpp_tests
PRIVATE
${HEADERS_PATH}
)
target_link_libraries(stronger_cpp_tests
PRIVATE
Catch2::Catch2WithMain
)

# Download NamedType for benchmarks ____________________________________________________________________________________

add_custom_target(download_NamedType
COMMAND ${CMAKE_COMMAND} -E env python3 ${CMAKE_CURRENT_SOURCE_DIR}/tests/benchmarks/get-NamedType.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Getting NamedType library for benchmarks"
)

# Runtime benchmarks ___________________________________________________________________________________________________

add_executable(stronger_cpp_benchmarks
tests/benchmarks/benchmarks.cpp
)
add_dependencies(stronger_cpp_benchmarks make_header_only download_NamedType)
target_include_directories(stronger_cpp_benchmarks
PRIVATE
${HEADERS_PATH}
)
target_link_libraries(stronger_cpp_benchmarks
PRIVATE
Catch2::Catch2WithMain
)

endif ()
24 changes: 20 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# stronger-cpp [![Build + Tests](https://github.com/Teskann/stronger-cpp/actions/workflows/ci.yml/badge.svg)](https://github.com/Teskann/stronger-cpp/actions/workflows/ci.yml)

# stronger-cpp [![Build + Tests](https://github.com/Teskann/stronger-cpp/actions/workflows/ci.yml/badge.svg)](https://github.com/Teskann/stronger-cpp/actions/workflows/ci.yml) [![CPM](https://github.com/teskann/stronger-cpp/actions/workflows/cpm.yml/badge.svg)](https://github.com/teskann/stronger-cpp/actions/workflows/cpm.yml)

### Single-header C++23 strong typing library

Expand All @@ -15,7 +14,7 @@ making it harder to accidentally mix or misuse variables in C++ code.*
- ✅ No visible runtime overhead. <sup>[[see more]](#runtime)</sup>
- ✅ Tested at compile time (strong guarantee against undefined behaviors)

# Table of Contents
## Table of Contents

* [Usage](#usage)
* [Basics](#basics)
Expand All @@ -34,6 +33,9 @@ making it harder to accidentally mix or misuse variables in C++ code.*
* [Compiling the library header](#compiling-the-library-header)
* [Compiling C++ file](#compiling-this-cpp-file)
* [Runtime](#runtime)
* [Get it](#get-it)
* [From release](#from-release)
* [CPM](#using-cpm)
* [Build from source](#build-from-source)
* [Debug](#debug)
* [Release](#release)
Expand All @@ -57,7 +59,7 @@ Once declared, you can use `Amount` and `Name` in your code:

```C++
void print_info(const Name& name, Amount amount) {
std::println("{} gave {.2f}$", amount);
std::println("{} gave {.2f}$", name, amount);
}

Name alice{"Alice"s};
Expand Down Expand Up @@ -386,6 +388,20 @@ is close to 1 ms.
We can conclude that **there is no visible runtime overhead when using
a strong typing library, no matter if it is NamedType or stronger-cpp**.

## Get it

### Using CPM

```cmake
# Get any version (here getting the latest commit on master)
CPMAddPackage("gh:teskann/stronger-cpp#master")
target_link_libraries(YOUR_TARGET PRIVATE stronger-cpp::stronger-cpp)
```

### From release

You can download the latest release from [here](https://github.com/Teskann/stronger-cpp/releases/latest).

## Build from source

Clone the repository and make sure you have conan installed:
Expand Down
8 changes: 8 additions & 0 deletions tests/cpm/CMakeLists.txt.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.31)
project(cpmtest)

include(cmake/CPM.cmake)
CPMAddPackage("gh:teskann/stronger-cpp#__COMMIT_PLACEHOLDER__")

add_executable(cpmtest main.cpp)
target_link_libraries(cpmtest PRIVATE stronger-cpp::stronger-cpp)
11 changes: 11 additions & 0 deletions tests/cpm/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2025 Clément Metz
// Licensed under the MIT License. See LICENSE file for details.

#include <iostream>
#include <stronger.hpp>

int main() {
stronger::strong_type<double, stronger::tag()> a{ 1.0 };
std::cout << "Hello, World!" << a << std::endl;
return 0;
}
Loading
Loading