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
18 changes: 15 additions & 3 deletions include/iris/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,27 @@

// SPDX-License-Identifier: MIT

#include <concepts>
#include <string>
#include <string_view>

namespace iris {

template<class T>
concept StringLike = requires(T t) {
std::basic_string_view{t};
};
concept CharLike =
std::same_as<T, char> ||
std::same_as<T, char32_t> ||
std::same_as<T, wchar_t> ||
std::same_as<T, char8_t> ||
std::same_as<T, char16_t>;

template<class T>
concept StringLike =
std::convertible_to<T, std::basic_string_view<char>> ||
std::convertible_to<T, std::basic_string_view<char32_t>> ||
std::convertible_to<T, std::basic_string_view<wchar_t>> ||
std::convertible_to<T, std::basic_string_view<char8_t>> ||
std::convertible_to<T, std::basic_string_view<char16_t>>;

template<class T>
concept NotStringLike = !StringLike<T>;
Expand Down
42 changes: 42 additions & 0 deletions test/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
#include <iris/type_traits.hpp>
#include <iris/requirements.hpp>
#include <iris/compare.hpp>
#include <iris/string.hpp>
#include <iris/fixed_string.hpp>
#include <iris/exception.hpp>
#include <iris/hash.hpp>

#include <concepts>
#include <string>
#include <string_view>
#include <utility>
#include <type_traits>
#include <ranges>
Expand Down Expand Up @@ -448,6 +451,45 @@ TEST_CASE("synth_three_way")
STATIC_CHECK(iris::cmp::synth_three_way{}(NoThreeWay{0}, NoThreeWay{1}) == std::weak_ordering::less);
}

TEST_CASE("StringLike")
{
STATIC_CHECK(iris::StringLike<char const*>);
STATIC_CHECK(iris::StringLike<wchar_t const*>);
STATIC_CHECK(iris::StringLike<char8_t const*>);
STATIC_CHECK(iris::StringLike<char16_t const*>);
STATIC_CHECK(iris::StringLike<char32_t const*>);

STATIC_CHECK(iris::StringLike<std::string>);
STATIC_CHECK(iris::StringLike<std::wstring>);
STATIC_CHECK(iris::StringLike<std::u8string>);
STATIC_CHECK(iris::StringLike<std::u16string>);
STATIC_CHECK(iris::StringLike<std::u32string>);

STATIC_CHECK(iris::StringLike<std::string_view>);
STATIC_CHECK(iris::StringLike<std::wstring_view>);
STATIC_CHECK(iris::StringLike<std::u8string_view>);
STATIC_CHECK(iris::StringLike<std::u16string_view>);
STATIC_CHECK(iris::StringLike<std::u32string_view>);

struct InvalidValueRange
{
struct Invalid { Invalid(Invalid const&) = delete; };

using value_type = Invalid;
value_type const* begin() const { return nullptr; }
value_type const* end() const { return nullptr; }
std::size_t size() const { return 0; }
};
static_assert(std::ranges::sized_range<InvalidValueRange>);
static_assert(std::ranges::contiguous_range<InvalidValueRange>);

// hard error as per [strings.general]/1
//std::basic_string_view sv{InvalidValueRange{}};

// should NOT yield hard error
STATIC_CHECK(!iris::StringLike<InvalidValueRange>);
}

TEST_CASE("fixed_string")
{
using namespace std::string_view_literals;
Expand Down
Loading