From d30a94ca6129302823b1bc91945cb8461c1e3e73 Mon Sep 17 00:00:00 2001 From: shogo314 Date: Sun, 11 Feb 2024 12:44:50 +0900 Subject: [PATCH] add assign --- cpp/rolling-hash.hpp | 72 ++++++++++++++++++++++++++++++++++++++------ cpp/traits.hpp | 19 ++++++++++++ 2 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 cpp/traits.hpp diff --git a/cpp/rolling-hash.hpp b/cpp/rolling-hash.hpp index 1e79cb5..f3d174a 100644 --- a/cpp/rolling-hash.hpp +++ b/cpp/rolling-hash.hpp @@ -5,6 +5,8 @@ #include #include +#include "traits.hpp" + struct RHString; /** @@ -116,13 +118,19 @@ struct RHString { RHString(RollingHash& rh) : rh(rh), sz(0), hash1(0), hash2(0) {} RHString(RollingHash& rh, size_t sz, unsigned long long hash1, unsigned long long hash2) : rh(rh), sz(sz), hash1(hash1), hash2(hash2) {} RHString(const RHString& o) : rh(o.rh), sz(o.sz), hash1(o.hash1), hash2(o.hash2) {} - template - RHString(RollingHash& rh, R s) : rh(rh) { - using std::begin, std::end; + template >> + RHString(RollingHash& rh, R&& s) : rh(rh) { + using std::begin, std::end, std::rbegin, std::rend; sz = std::distance(begin(s), end(s)); hash1 = rh.build(begin(s), end(s)).back(); hash2 = rh.build(rbegin(s), rend(s)).back(); } + template >> + RHString(RollingHash& rh, T x) : rh(rh) { + sz = 1; + hash1 = x; + hash2 = x; + } /** * @brief 回文か否か @@ -150,22 +158,68 @@ struct RHString { sz += o.sz; return *this; } - RHString& operator=(const RHString& o) { + /** + * @brief 再代入する + */ + void assign(const RHString& o) { assert(&rh == &o.rh); sz = o.sz; hash1 = o.hash1; hash2 = o.hash2; - return *this; } /** - * @brief 文字列などで初期化する + * @brief 文字列(std::string)などで再代入する */ - template - RHString& assign(const R& s) { + template >> + void assign(R&& s) { using std::begin, std::end; sz = std::distance(begin(s), end(s)); hash1 = rh.build(begin(s), end(s)).back(); hash2 = rh.build(rbegin(s), rend(s)).back(); + } + /** + * @brief 文字(char)などで再代入する + */ + template >> + void assign(T x) { + sz = 1; + hash1 = x; + hash2 = x; + } + /** + * @brief const char*で再代入する + */ + void assign(const char* s) { + assign(std::string(s)); + } + /** + * @brief 再代入する + */ + RHString& operator=(const RHString& o) { + assign(o); + return *this; + } + /** + * @brief 文字列(std::string)などで再代入する + */ + template >> + RHString& operator=(R&& s) { + assign(s); + return *this; + } + /** + * @brief 文字(char)などで再代入する + */ + template >> + RHString& operator=(T x) { + assign(x); + return *this; + } + /** + * @brief const char*で再代入する + */ + RHString& operator=(const char* s) { + assign(s); return *this; } friend RHString operator+(const RHString& t1, const RHString& t2) { @@ -175,7 +229,7 @@ struct RHString { } friend bool operator==(const RHString& t1, const RHString& t2) { assert(&t1.rh == &t2.rh); - return t1.hash1 == t2.hash1 && t1.hash2 == t2.hash2; + return t1.sz == t2.sz && t1.hash1 == t2.hash1 && t1.hash2 == t2.hash2; } friend bool operator!=(const RHString& t1, const RHString& t2) { return !(t1 == t2); } }; diff --git a/cpp/traits.hpp b/cpp/traits.hpp new file mode 100644 index 0000000..590a8c5 --- /dev/null +++ b/cpp/traits.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + +namespace detail { +using std::begin, std::end; + +template +struct is_range_impl : std::false_type {}; +template +struct is_range_impl()), end(std::declval()))>> : std::true_type {}; +} // namespace detail + +template +struct is_range : detail::is_range_impl::type {}; +template +inline constexpr bool is_range_v = is_range::value;