Skip to content

Commit 0f03c1a

Browse files
authored
Fix: constexpr string (#417)
1 parent 179ef9f commit 0f03c1a

2 files changed

Lines changed: 39 additions & 30 deletions

File tree

src/rdf4cpp/datatypes/registry/util/ConstexprString.hpp

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,57 +18,66 @@ namespace rdf4cpp::datatypes::registry::util {
1818
*/
1919
template<size_t N>
2020
struct ConstexprString {
21-
std::array<char, N> value;
21+
std::array<char, N> value{};
2222

23-
constexpr ConstexprString(const char (&str)[N]) noexcept {
23+
constexpr ConstexprString() noexcept = default;
24+
25+
/**
26+
* @param str null-terminated char array/string literal
27+
*/
28+
constexpr ConstexprString(char const (&str)[N]) noexcept {
2429
std::copy_n(str, N, value.data());
2530
}
31+
2632
constexpr ConstexprString(std::string_view v) {
27-
if (v.size()+1 != N)
28-
throw std::invalid_argument{"size missmatch"};
29-
std::copy_n(v.data(), N-1, value.data());
30-
value[N-1] = 0;
33+
if (v.size() != N - 1) {
34+
throw std::invalid_argument{"size mismatch"};
35+
}
36+
37+
std::copy_n(v.data(), N - 1, value.data());
38+
// implicitly null terminated by default init of array
3139
}
32-
constexpr ConstexprString() = default;
3340

34-
constexpr operator std::string_view() const noexcept {
35-
return std::string_view{value.data(), value.size() - 1};
41+
[[nodiscard]] constexpr char const *data() const noexcept {
42+
return value.data();
3643
}
3744

38-
[[nodiscard]] constexpr char const *c_str() const noexcept {
45+
[[nodiscard]] constexpr char *data() noexcept {
3946
return value.data();
4047
}
4148

49+
[[nodiscard]] static constexpr size_t size() noexcept {
50+
return N - 1; // exclude null terminator
51+
}
52+
53+
[[nodiscard]] constexpr std::string_view view() const noexcept {
54+
return std::string_view{data(), size()};
55+
}
56+
57+
constexpr operator std::string_view() const noexcept {
58+
return view();
59+
}
60+
4261
template<size_t M>
4362
constexpr std::strong_ordering operator<=>(ConstexprString<M> const &other) const noexcept {
44-
auto min = std::min(M, N);
45-
for (size_t i = 0; i < min; ++i) {
46-
std::strong_ordering cmp = this->value[i] <=> other.value[i];
47-
if (cmp != std::strong_ordering::equal)
48-
return cmp;
49-
}
50-
std::strong_ordering cmp = N <=> M;
51-
return cmp;
63+
return view() <=> other.view();
5264
}
5365

5466
template<size_t M>
5567
constexpr bool operator==(ConstexprString<M> const &other) const noexcept {
56-
if (M == N) {
57-
return (*this <=> other == std::strong_ordering::equal);
68+
if constexpr (M == N) {
69+
return value == other.value;
5870
} else {
5971
return false;
6072
}
6173
}
6274

63-
[[nodiscard]] constexpr size_t size() const noexcept {
64-
return N;
65-
}
66-
6775
template<size_t M>
68-
constexpr ConstexprString<M+N-1> operator+(const ConstexprString<M>& other) const noexcept {
69-
ConstexprString<M+N-1> r{};
70-
std::copy_n(this->value.data(), N-1, r.value.data());
71-
std::copy_n(other.value.data(), M-1, r.value.data() + (N-1));
76+
constexpr ConstexprString<M+N-1> operator+(ConstexprString<M> const &other) const noexcept {
77+
ConstexprString<M+N-1> r{}; // only include a single null terminator N+M would include 2
78+
std::copy_n(data(), size(), r.data());
79+
std::copy_n(other.data(), other.size(), r.data() + size());
80+
// implicitly null terminated by default init of array
7281
return r;
7382
}
7483
};
@@ -83,7 +92,7 @@ struct ConstexprStringHolder {
8392
template<size_t N>
8493
struct std::formatter<rdf4cpp::datatypes::registry::util::ConstexprString<N>> : std::formatter<std::string_view> {
8594
auto format(rdf4cpp::datatypes::registry::util::ConstexprString<N> const &s, format_context& ctx) const {
86-
return formatter<string_view>::format(static_cast<std::string_view>(s), ctx);
95+
return formatter<string_view>::format(s.view(), ctx);
8796
}
8897
};
8998

tests/serializer/tests_Serialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,4 +435,4 @@ TEST_CASE("extended") {
435435
}
436436

437437
static_assert(datatypes::registry::util::ConstexprString("abc")+datatypes::registry::util::ConstexprString("def") == datatypes::registry::util::ConstexprString("abcdef"));
438-
static_assert((datatypes::registry::util::ConstexprString("abc")+datatypes::registry::util::ConstexprString("def")).size() == 7);
438+
static_assert((datatypes::registry::util::ConstexprString("abc")+datatypes::registry::util::ConstexprString("def")).size() == 6);

0 commit comments

Comments
 (0)