diff --git a/include/rsl/strong_type.hpp b/include/rsl/strong_type.hpp new file mode 100644 index 0000000..54f1c50 --- /dev/null +++ b/include/rsl/strong_type.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace rsl { + +/** @file */ + +/** + * @brief Class template for creating strong type aliases + * + * @tparam T value type + * @tparam Tag Tag type to disambiguate separate type aliases + */ +template +class StrongType { + T value_; + + public: + constexpr explicit StrongType(T value) : value_(std::move(value)) {} + [[nodiscard]] constexpr T& get() { return value_; } + [[nodiscard]] constexpr const T& get() const { return value_; } + [[nodiscard]] constexpr explicit operator T() const { return value_; } +}; + +} // namespace rsl diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d575a9f..427b5a7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(test-rsl random.cpp static_string.cpp static_vector.cpp + strong_type.cpp try.cpp) target_link_libraries(test-rsl PRIVATE rsl::rsl diff --git a/tests/strong_type.cpp b/tests/strong_type.cpp new file mode 100644 index 0000000..fefede3 --- /dev/null +++ b/tests/strong_type.cpp @@ -0,0 +1,27 @@ +#include + +#include + +TEST_CASE("rsl::StrongType") { + using StrongInt = rsl::StrongType; // For testing constexpr support + using StrongString = + rsl::StrongType; // For testing non-constexpr types + + SECTION("Construction") { + constexpr auto strong_int = StrongInt(42); + STATIC_CHECK(strong_int.get() == 42); + STATIC_CHECK(int{strong_int} == 42); + STATIC_CHECK(int(strong_int) == 42); + + auto const strong_string = StrongString("abcdefg"); + CHECK(strong_string.get() == "abcdefg"); + CHECK(std::string{strong_string} == "abcdefg"); + CHECK(std::string(strong_string) == "abcdefg"); + } + + SECTION("get()") { + auto strong_int = StrongInt(1337); + strong_int.get() = 100; + CHECK(strong_int.get() == 100); + } +}