From f5fa722626d67afca441d5ac6f172854c3b5287a Mon Sep 17 00:00:00 2001 From: Luke Valenty Date: Tue, 10 Dec 2024 15:22:01 -0800 Subject: [PATCH] Add GROOV_STATIC_ASSERT for better compile time error messages --- CMakeLists.txt | 2 +- include/groov/config.hpp | 28 +++++++++++++++++++++++---- include/groov/path.hpp | 7 +++++++ test/fail/group_unresolvable_path.cpp | 2 +- test/path.cpp | 9 +++++++++ 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 589bb5c..ba7d534 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ endif() add_versioned_package("gh:boostorg/mp11#boost-1.83.0") add_versioned_package("gh:intel/cpp-baremetal-concurrency#7c5b26c") -add_versioned_package("gh:intel/cpp-std-extensions#5530b5d") +add_versioned_package("gh:intel/cpp-std-extensions#57c87c2") add_versioned_package("gh:intel/cpp-baremetal-senders-and-receivers#73d95bc") add_versioned_package("gh:intel/safe-arithmetic#9ea549a") diff --git a/include/groov/config.hpp b/include/groov/config.hpp index 5f17691..79dea09 100644 --- a/include/groov/config.hpp +++ b/include/groov/config.hpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include @@ -190,13 +192,31 @@ template struct any_resolves_q { template using fn = boost::mp11::mp_any_of_q>; }; +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define GROOV_STATIC_ASSERT(cond, fmt, ...) \ + STATIC_ASSERT( \ + cond, \ + " (/o.o)/ _|_|_ . o O (HEY, LOOK HERE!!!) ~~ GROOV ERROR: " fmt \ + __VA_OPT__(, ) __VA_ARGS__) + +template +constexpr static auto path_names(boost::mp11::mp_list) { + using namespace stdx::literals; + return stdx::tuple{Paths::to_string()...}.join( + ""_cts, [](auto lhs, auto rhs) { return lhs + ", "_cts + rhs; }); +} + template constexpr auto check_valid_config() -> void { static_assert(boost::mp11::mp_is_set::value, "Duplicate path passed to group"); - static_assert( - boost::mp11::mp_all_of_q>::value, - "Unresolvable path passed to group"); + + using bad_paths = + boost::mp11::mp_remove_if_q>; + + GROOV_STATIC_ASSERT(boost::mp11::mp_empty::value, + "Unresolvable path(s) [{}] passed to group [{}]", + path_names(bad_paths{}), CX_VALUE(G::name)); + stdx::template_for_each([]() { using rest = boost::mp11::mp_remove; static_assert(boost::mp11::mp_none_of_q>::value, diff --git a/include/groov/path.hpp b/include/groov/path.hpp index 3eaea94..d5f5a4b 100644 --- a/include/groov/path.hpp +++ b/include/groov/path.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -50,6 +51,12 @@ template struct path { constexpr static auto empty = std::bool_constant{}; + constexpr static auto to_string() { + using namespace stdx::literals; + return stdx::tuple{Parts...}.join( + ""_cts, [](auto lhs, auto rhs) { return lhs + "."_cts + rhs; }); + } + private: friend constexpr auto operator==(path, path) -> bool = default; diff --git a/test/fail/group_unresolvable_path.cpp b/test/fail/group_unresolvable_path.cpp index f6ac86d..d7f4b4e 100644 --- a/test/fail/group_unresolvable_path.cpp +++ b/test/fail/group_unresolvable_path.cpp @@ -4,7 +4,7 @@ #include -// EXPECT: Unresolvable path passed to group +// EXPECT: Unresolvable path\(s\) \[reg0.field1\] passed to group \[group\] namespace { struct bus { diff --git a/test/path.cpp b/test/path.cpp index 5ef0bcd..deb1348 100644 --- a/test/path.cpp +++ b/test/path.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include @@ -95,3 +97,10 @@ TEST_CASE("path is pathlike", "[path]") { static_assert(groov::pathlike); static_assert(not groov::valued_pathlike); } + +TEST_CASE("convert to string", "[path]") { + using namespace stdx::literals; + using namespace groov::literals; + static_assert(("reg"_r / "field"_f).to_string() == "reg.field"_cts); + static_assert(groov::path<>::to_string() == ""_cts); +}