Skip to content

Commit fe9e3a1

Browse files
authored
Fix StringLike for non-string-like range (#48)
* Add test for `StringLike` * Fix `StringLike` for non-string-like range
1 parent cec583e commit fe9e3a1

2 files changed

Lines changed: 57 additions & 3 deletions

File tree

include/iris/string.hpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,27 @@
33

44
// SPDX-License-Identifier: MIT
55

6+
#include <concepts>
67
#include <string>
78
#include <string_view>
89

910
namespace iris {
1011

1112
template<class T>
12-
concept StringLike = requires(T t) {
13-
std::basic_string_view{t};
14-
};
13+
concept CharLike =
14+
std::same_as<T, char> ||
15+
std::same_as<T, char32_t> ||
16+
std::same_as<T, wchar_t> ||
17+
std::same_as<T, char8_t> ||
18+
std::same_as<T, char16_t>;
19+
20+
template<class T>
21+
concept StringLike =
22+
std::convertible_to<T, std::basic_string_view<char>> ||
23+
std::convertible_to<T, std::basic_string_view<char32_t>> ||
24+
std::convertible_to<T, std::basic_string_view<wchar_t>> ||
25+
std::convertible_to<T, std::basic_string_view<char8_t>> ||
26+
std::convertible_to<T, std::basic_string_view<char16_t>>;
1527

1628
template<class T>
1729
concept NotStringLike = !StringLike<T>;

test/core.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
#include <iris/type_traits.hpp>
66
#include <iris/requirements.hpp>
77
#include <iris/compare.hpp>
8+
#include <iris/string.hpp>
89
#include <iris/fixed_string.hpp>
910
#include <iris/exception.hpp>
1011
#include <iris/hash.hpp>
1112

1213
#include <concepts>
14+
#include <string>
15+
#include <string_view>
1316
#include <utility>
1417
#include <type_traits>
1518
#include <ranges>
@@ -448,6 +451,45 @@ TEST_CASE("synth_three_way")
448451
STATIC_CHECK(iris::cmp::synth_three_way{}(NoThreeWay{0}, NoThreeWay{1}) == std::weak_ordering::less);
449452
}
450453

454+
TEST_CASE("StringLike")
455+
{
456+
STATIC_CHECK(iris::StringLike<char const*>);
457+
STATIC_CHECK(iris::StringLike<wchar_t const*>);
458+
STATIC_CHECK(iris::StringLike<char8_t const*>);
459+
STATIC_CHECK(iris::StringLike<char16_t const*>);
460+
STATIC_CHECK(iris::StringLike<char32_t const*>);
461+
462+
STATIC_CHECK(iris::StringLike<std::string>);
463+
STATIC_CHECK(iris::StringLike<std::wstring>);
464+
STATIC_CHECK(iris::StringLike<std::u8string>);
465+
STATIC_CHECK(iris::StringLike<std::u16string>);
466+
STATIC_CHECK(iris::StringLike<std::u32string>);
467+
468+
STATIC_CHECK(iris::StringLike<std::string_view>);
469+
STATIC_CHECK(iris::StringLike<std::wstring_view>);
470+
STATIC_CHECK(iris::StringLike<std::u8string_view>);
471+
STATIC_CHECK(iris::StringLike<std::u16string_view>);
472+
STATIC_CHECK(iris::StringLike<std::u32string_view>);
473+
474+
struct InvalidValueRange
475+
{
476+
struct Invalid { Invalid(Invalid const&) = delete; };
477+
478+
using value_type = Invalid;
479+
value_type const* begin() const { return nullptr; }
480+
value_type const* end() const { return nullptr; }
481+
std::size_t size() const { return 0; }
482+
};
483+
static_assert(std::ranges::sized_range<InvalidValueRange>);
484+
static_assert(std::ranges::contiguous_range<InvalidValueRange>);
485+
486+
// hard error as per [strings.general]/1
487+
//std::basic_string_view sv{InvalidValueRange{}};
488+
489+
// should NOT yield hard error
490+
STATIC_CHECK(!iris::StringLike<InvalidValueRange>);
491+
}
492+
451493
TEST_CASE("fixed_string")
452494
{
453495
using namespace std::string_view_literals;

0 commit comments

Comments
 (0)