diff options
author | crupest <crupest@outlook.com> | 2019-03-21 22:22:02 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-03-21 22:22:02 +0800 |
commit | 962dc18ee4827b464764ec3708be3d00a9143971 (patch) | |
tree | 3eea13894a14a26f2e2de07d3d6bc7789d409864 /src | |
parent | afa2a079562d810e5ef611071b21a3568da9dfca (diff) | |
download | cru-962dc18ee4827b464764ec3708be3d00a9143971.tar.gz cru-962dc18ee4827b464764ec3708be3d00a9143971.tar.bz2 cru-962dc18ee4827b464764ec3708be3d00a9143971.zip |
...
Diffstat (limited to 'src')
-rw-r--r-- | src/base.hpp | 8 | ||||
-rw-r--r-- | src/cru_debug.cpp | 2 | ||||
-rw-r--r-- | src/cru_debug.hpp | 4 | ||||
-rw-r--r-- | src/ui/content_control.cpp | 32 | ||||
-rw-r--r-- | src/ui/content_control.hpp | 31 | ||||
-rw-r--r-- | src/ui/control.cpp | 110 | ||||
-rw-r--r-- | src/ui/control.hpp | 136 | ||||
-rw-r--r-- | src/ui/controls/flex_layout.hpp | 4 | ||||
-rw-r--r-- | src/ui/controls/text_block.hpp | 2 | ||||
-rw-r--r-- | src/ui/layout_control.cpp | 52 | ||||
-rw-r--r-- | src/ui/layout_control.hpp | 33 | ||||
-rw-r--r-- | src/ui/no_child_control.cpp | 5 | ||||
-rw-r--r-- | src/ui/no_child_control.hpp | 26 | ||||
-rw-r--r-- | src/ui/window.cpp | 86 | ||||
-rw-r--r-- | src/ui/window.hpp | 9 | ||||
-rw-r--r-- | src/util/format.hpp | 42 |
16 files changed, 303 insertions, 279 deletions
diff --git a/src/base.hpp b/src/base.hpp index a62a745b..2c511c4b 100644 --- a/src/base.hpp +++ b/src/base.hpp @@ -7,9 +7,6 @@ #include <string_view> namespace cru { -template <typename T> -struct type_tag {}; - // typedefs using String = std::wstring; using MultiByteString = std::string; @@ -38,9 +35,4 @@ struct Interface { [[noreturn]] inline void UnreachableCode() { throw std::logic_error("Unreachable code."); } - -inline void Require(const bool condition, - const MultiByteStringView& error_message) { - if (!condition) throw std::invalid_argument(error_message.data()); -} } // namespace cru diff --git a/src/cru_debug.cpp b/src/cru_debug.cpp index b9226132..331d2bce 100644 --- a/src/cru_debug.cpp +++ b/src/cru_debug.cpp @@ -3,7 +3,9 @@ #include "system_headers.hpp" namespace cru::debug { +#ifdef CRU_DEBUG void DebugMessage(const StringView& message) { ::OutputDebugStringW(message.data()); } +#endif } // namespace cru::debug diff --git a/src/cru_debug.hpp b/src/cru_debug.hpp index 9c22a24f..58431d56 100644 --- a/src/cru_debug.hpp +++ b/src/cru_debug.hpp @@ -7,7 +7,11 @@ #include "util/format.hpp" namespace cru::debug { +#ifdef CRU_DEBUG void DebugMessage(const StringView& message); +#else +inline void DebugMessage(const StringView& message) {} +#endif #ifdef CRU_DEBUG inline void DebugTime(const std::function<void()>& action, diff --git a/src/ui/content_control.cpp b/src/ui/content_control.cpp new file mode 100644 index 00000000..960867b2 --- /dev/null +++ b/src/ui/content_control.cpp @@ -0,0 +1,32 @@ +#include "content_control.hpp" + +#include "window.hpp" + +namespace cru::ui { +ContentControl::ContentControl() + : child_vector_{nullptr}, child_(child_vector_[0]) {} + +ContentControl::~ContentControl() { delete child_; } + +void ContentControl::SetChild(Control* child) { + if (dynamic_cast<Window*>(child)) + throw std::invalid_argument("Can't add a window as child."); + + if (child == child_) return; + + const auto window = GetWindow(); + const auto old_child = child_; + child_ = child; + if (old_child) { + old_child->_SetParent(nullptr); + old_child->_SetDescendantWindow(nullptr); + } + if (child) { + child->_SetParent(this); + child->_SetDescendantWindow(window); + } + OnChildChanged(old_child, child); +} + +void ContentControl::OnChildChanged(Control* old_child, Control* new_child) {} +} // namespace cru::ui diff --git a/src/ui/content_control.hpp b/src/ui/content_control.hpp new file mode 100644 index 00000000..88e7f60f --- /dev/null +++ b/src/ui/content_control.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "pre.hpp" + +#include "control.hpp" + +namespace cru::ui { +class ContentControl : public Control { + protected: + ContentControl(); + + public: + ContentControl(const ContentControl& other) = delete; + ContentControl(ContentControl&& other) = delete; + ContentControl& operator=(const ContentControl& other) = delete; + ContentControl& operator=(ContentControl&& other) = delete; + ~ContentControl() override; + + const std::vector<Control*>& GetChildren() const override final { + return child_vector_; + } + Control* GetChild() const { return child_; } + void SetChild(Control* child); + + protected: + virtual void OnChildChanged(Control* old_child, Control* new_child); + + private: + std::vector<Control*> child_vector_; + Control*& child_; +}; +} // namespace cru::ui diff --git a/src/ui/control.cpp b/src/ui/control.cpp index 98986d3c..e19754dc 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -35,14 +35,14 @@ void Control::_SetDescendantWindow(Window* window) { void Control::TraverseDescendants( const std::function<void(Control*)>& predicate) { - TraverseDescendantsInternal(this, predicate); + _TraverseDescendants(this, predicate); } -void Control::TraverseDescendantsInternal( +void Control::_TraverseDescendants( Control* control, const std::function<void(Control*)>& predicate) { predicate(control); for (auto c : control->GetChildren()) - TraverseDescendantsInternal(c, predicate); + _TraverseDescendants(c, predicate); } bool Control::RequestFocus() { auto window = GetWindow(); @@ -76,108 +76,4 @@ void Control::OnDetachToWindow(Window* window) {} void Control::OnMouseClickBegin(MouseButton button) {} void Control::OnMouseClickEnd(MouseButton button) {} - -const std::vector<Control*> NoChildControl::empty_control_vector{}; - -ContentControl::ContentControl() - : child_vector_{nullptr}, child_(child_vector_[0]) {} - -ContentControl::~ContentControl() { delete child_; } - -void ContentControl::SetChild(Control* child) { - if (child == child_) return; - - const auto window = GetWindow(); - const auto old_child = child_; - child_ = child; - if (old_child) { - old_child->_SetParent(nullptr); - old_child->_SetDescendantWindow(nullptr); - } - if (child) { - child->_SetParent(this); - child->_SetDescendantWindow(window); - } - OnChildChanged(old_child, child); -} - -void ContentControl::OnChildChanged(Control* old_child, Control* new_child) {} - -void ControlAddChildCheck(Control* control) { - if (control->GetParent() != nullptr) - throw std::invalid_argument("The control already has a parent."); - - if (dynamic_cast<Window*>(control)) - throw std::invalid_argument("Can't add a window as child."); -} - -Layout::~Layout() { - for (const auto child : children_) delete child; -} - -void Layout::AddChild(Control* control, const int position) { - ControlAddChildCheck(control); - - if (position < 0 || static_cast<decltype(children_.size())>(position) > - this->children_.size()) - throw std::invalid_argument("The position is out of range."); - - children_.insert(this->children_.cbegin() + position, control); - - control->_SetParent(this); - control->_SetDescendantWindow(GetWindow()); - - OnAddChild(control, position); -} - -void Layout::RemoveChild(const int position) { - if (position < 0 || static_cast<decltype(this->children_.size())>(position) >= - this->children_.size()) - throw std::invalid_argument("The position is out of range."); - - const auto i = children_.cbegin() + position; - const auto child = *i; - - children_.erase(i); - - child->_SetParent(nullptr); - child->_SetDescendantWindow(nullptr); - - OnRemoveChild(child, position); -} - -void Layout::OnAddChild(Control* child, int position) {} - -void Layout::OnRemoveChild(Control* child, int position) {} - -std::list<Control*> GetAncestorList(Control* control) { - std::list<Control*> l; - while (control != nullptr) { - l.push_front(control); - control = control->GetParent(); - } - return l; -} - -Control* FindLowestCommonAncestor(Control* left, Control* right) { - if (left == nullptr || right == nullptr) return nullptr; - - auto&& left_list = GetAncestorList(left); - auto&& right_list = GetAncestorList(right); - - // the root is different - if (left_list.front() != right_list.front()) return nullptr; - - // find the last same control or the last control (one is ancestor of the - // other) - auto left_i = left_list.cbegin(); - auto right_i = right_list.cbegin(); - while (true) { - if (left_i == left_list.cend()) return *(--left_i); - if (right_i == right_list.cend()) return *(--right_i); - if (*left_i != *right_i) return *(--left_i); - ++left_i; - ++right_i; - } -} } // namespace cru::ui diff --git a/src/ui/control.hpp b/src/ui/control.hpp index 9ff407b0..8454e981 100644 --- a/src/ui/control.hpp +++ b/src/ui/control.hpp @@ -48,7 +48,7 @@ class Control : public Object { void _SetDescendantWindow(Window* window); private: - static void TraverseDescendantsInternal( + static void _TraverseDescendants( Control* control, const std::function<void(Control*)>& predicate); public: @@ -110,138 +110,4 @@ class Control : public Object { Cursor::Ptr cursor_{}; }; - -class NoChildControl : public Control { - private: - static const std::vector<Control*> empty_control_vector; - - protected: - NoChildControl() = default; - - public: - NoChildControl(const NoChildControl& other) = delete; - NoChildControl(NoChildControl&& other) = delete; - NoChildControl& operator=(const NoChildControl& other) = delete; - NoChildControl& operator=(NoChildControl&& other) = delete; - ~NoChildControl() override = default; - - protected: - const std::vector<Control*>& GetChildren() const override final { - return empty_control_vector; - } -}; - -class ContentControl : public Control { - protected: - ContentControl(); - - public: - ContentControl(const ContentControl& other) = delete; - ContentControl(ContentControl&& other) = delete; - ContentControl& operator=(const ContentControl& other) = delete; - ContentControl& operator=(ContentControl&& other) = delete; - ~ContentControl() override; - - const std::vector<Control*>& GetChildren() const override final { - return child_vector_; - } - Control* GetChild() const { return child_; } - void SetChild(Control* child); - - protected: - virtual void OnChildChanged(Control* old_child, Control* new_child); - - private: - std::vector<Control*> child_vector_; - Control*& child_; -}; - -class Layout : public Control { - protected: - Layout() = default; - - public: - Layout(const Layout& other) = delete; - Layout(Layout&& other) = delete; - Layout& operator=(const Layout& other) = delete; - Layout& operator=(Layout&& other) = delete; - ~Layout() override; - - const std::vector<Control*>& GetChildren() const override final { - return children_; - } - - void AddChild(Control* control, int position); - - void RemoveChild(int position); - - protected: - virtual void OnAddChild(Control* child, int position); - virtual void OnRemoveChild(Control* child, int position); - - private: - std::vector<Control*> children_; -}; - -//*************** region: event dispatcher helper *************** - -// Dispatch the event. -// -// This will raise routed event of the control and its parent and parent's -// parent ... (until "last_receiver" if it's not nullptr) with appropriate args. -// -// First tunnel from top to bottom possibly stopped by "handled" flag in -// EventArgs. Second bubble from bottom to top possibly stopped by "handled" -// flag in EventArgs. Last direct to each control. -// -// Args is of type "EventArgs". The first init argument is "sender", which is -// automatically bound to each receiving control. The second init argument is -// "original_sender", which is unchanged. And "args" will be perfectly forwarded -// as the rest arguments. -template <typename EventArgs, typename... Args> -void DispatchEvent(Control* const original_sender, - events::RoutedEvent<EventArgs> Control::*event_ptr, - Control* const last_receiver, Args&&... args) { - std::list<Control*> receive_list; - - auto parent = original_sender; - while (parent != last_receiver) { - receive_list.push_back(parent); - parent = parent->GetParent(); - } - - auto handled = false; - - // tunnel - for (auto i = receive_list.crbegin(); i != receive_list.crend(); ++i) { - EventArgs event_args(*i, original_sender, std::forward<Args>(args)...); - (*i->*event_ptr).tunnel.Raise(event_args); - if (event_args.IsHandled()) { - handled = true; - break; - } - } - - // bubble - if (!handled) { - for (auto i : receive_list) { - EventArgs event_args(i, original_sender, std::forward<Args>(args)...); - (i->*event_ptr).bubble.Raise(event_args); - if (event_args.IsHandled()) break; - } - } - - // direct - for (auto i : receive_list) { - EventArgs event_args(i, original_sender, std::forward<Args>(args)...); - (i->*event_ptr).direct.Raise(event_args); - } -} - -//*************** region: tree helper *************** - -// Find the lowest common ancestor. -// Return nullptr if "left" and "right" are not in the same tree. -Control* FindLowestCommonAncestor(Control* left, Control* right); - } // namespace cru::ui diff --git a/src/ui/controls/flex_layout.hpp b/src/ui/controls/flex_layout.hpp index 682ed8dc..2ab3e259 100644 --- a/src/ui/controls/flex_layout.hpp +++ b/src/ui/controls/flex_layout.hpp @@ -1,7 +1,7 @@ #pragma once #include "pre.hpp" -#include "ui/control.hpp" +#include "ui/layout_control.hpp" namespace cru::ui::render { class FlexLayoutRenderObject; @@ -9,7 +9,7 @@ class FlexLayoutRenderObject; namespace cru::ui::controls { -class FlexLayout : public Layout { +class FlexLayout : public LayoutControl { public: static constexpr auto control_type = L"FlexLayout"; diff --git a/src/ui/controls/text_block.hpp b/src/ui/controls/text_block.hpp index c345c5ab..4c443020 100644 --- a/src/ui/controls/text_block.hpp +++ b/src/ui/controls/text_block.hpp @@ -1,7 +1,7 @@ #pragma once #include "pre.hpp" -#include "ui/control.hpp" +#include "ui/no_child_control.hpp" namespace cru::ui::render { class TextRenderObject; diff --git a/src/ui/layout_control.cpp b/src/ui/layout_control.cpp new file mode 100644 index 00000000..d2b430dd --- /dev/null +++ b/src/ui/layout_control.cpp @@ -0,0 +1,52 @@ +#include "layout_control.hpp" + +#include "window.hpp" + +namespace cru::ui { +void ControlAddChildCheck(Control* control) { + if (control->GetParent() != nullptr) + throw std::invalid_argument("The control already has a parent."); + + if (dynamic_cast<Window*>(control)) + throw std::invalid_argument("Can't add a window as child."); +} + +LayoutControl::~LayoutControl() { + for (const auto child : children_) delete child; +} + +void LayoutControl::AddChild(Control* control, const int position) { + ControlAddChildCheck(control); + + if (position < 0 || static_cast<decltype(children_.size())>(position) > + this->children_.size()) + throw std::invalid_argument("The position is out of range."); + + children_.insert(this->children_.cbegin() + position, control); + + control->_SetParent(this); + control->_SetDescendantWindow(GetWindow()); + + OnAddChild(control, position); +} + +void LayoutControl::RemoveChild(const int position) { + if (position < 0 || static_cast<decltype(this->children_.size())>(position) >= + this->children_.size()) + throw std::invalid_argument("The position is out of range."); + + const auto i = children_.cbegin() + position; + const auto child = *i; + + children_.erase(i); + + child->_SetParent(nullptr); + child->_SetDescendantWindow(nullptr); + + OnRemoveChild(child, position); +} + +void LayoutControl::OnAddChild(Control* child, int position) {} + +void LayoutControl::OnRemoveChild(Control* child, int position) {} +} // namespace cru::ui diff --git a/src/ui/layout_control.hpp b/src/ui/layout_control.hpp new file mode 100644 index 00000000..53f53186 --- /dev/null +++ b/src/ui/layout_control.hpp @@ -0,0 +1,33 @@ +#pragma once +#include "pre.hpp" + +#include "control.hpp" + +namespace cru::ui { +class LayoutControl : public Control { + protected: + LayoutControl() = default; + + public: + LayoutControl(const LayoutControl& other) = delete; + LayoutControl(LayoutControl&& other) = delete; + LayoutControl& operator=(const LayoutControl& other) = delete; + LayoutControl& operator=(LayoutControl&& other) = delete; + ~LayoutControl() override; + + const std::vector<Control*>& GetChildren() const override final { + return children_; + } + + void AddChild(Control* control, int position); + + void RemoveChild(int position); + + protected: + virtual void OnAddChild(Control* child, int position); + virtual void OnRemoveChild(Control* child, int position); + + private: + std::vector<Control*> children_; +}; +} // namespace cru::ui diff --git a/src/ui/no_child_control.cpp b/src/ui/no_child_control.cpp new file mode 100644 index 00000000..e6bbe813 --- /dev/null +++ b/src/ui/no_child_control.cpp @@ -0,0 +1,5 @@ +#include "no_child_control.hpp" + +namespace cru::ui { +const std::vector<Control*> NoChildControl::empty_control_vector{}; +} diff --git a/src/ui/no_child_control.hpp b/src/ui/no_child_control.hpp new file mode 100644 index 00000000..26b5546f --- /dev/null +++ b/src/ui/no_child_control.hpp @@ -0,0 +1,26 @@ +#pragma once +#include "pre.hpp" + +#include "control.hpp" + +namespace cru::ui { +class NoChildControl : public Control { + private: + static const std::vector<Control*> empty_control_vector; + + protected: + NoChildControl() = default; + + public: + NoChildControl(const NoChildControl& other) = delete; + NoChildControl(NoChildControl&& other) = delete; + NoChildControl& operator=(const NoChildControl& other) = delete; + NoChildControl& operator=(NoChildControl&& other) = delete; + ~NoChildControl() override = default; + + protected: + const std::vector<Control*>& GetChildren() const override final { + return empty_control_vector; + } +}; +} // namespace cru::ui diff --git a/src/ui/window.cpp b/src/ui/window.cpp index f92811a7..b976ca6a 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -7,6 +7,92 @@ #include "render/window_render_object.hpp" namespace cru::ui { +namespace { +// Dispatch the event. +// +// This will raise routed event of the control and its parent and parent's +// parent ... (until "last_receiver" if it's not nullptr) with appropriate args. +// +// First tunnel from top to bottom possibly stopped by "handled" flag in +// EventArgs. Second bubble from bottom to top possibly stopped by "handled" +// flag in EventArgs. Last direct to each control. +// +// Args is of type "EventArgs". The first init argument is "sender", which is +// automatically bound to each receiving control. The second init argument is +// "original_sender", which is unchanged. And "args" will be perfectly forwarded +// as the rest arguments. +template <typename EventArgs, typename... Args> +void DispatchEvent(Control* const original_sender, + events::RoutedEvent<EventArgs> Control::*event_ptr, + Control* const last_receiver, Args&&... args) { + std::list<Control*> receive_list; + + auto parent = original_sender; + while (parent != last_receiver) { + receive_list.push_back(parent); + parent = parent->GetParent(); + } + + auto handled = false; + + // tunnel + for (auto i = receive_list.crbegin(); i != receive_list.crend(); ++i) { + EventArgs event_args(*i, original_sender, std::forward<Args>(args)...); + (*i->*event_ptr).tunnel.Raise(event_args); + if (event_args.IsHandled()) { + handled = true; + break; + } + } + + // bubble + if (!handled) { + for (auto i : receive_list) { + EventArgs event_args(i, original_sender, std::forward<Args>(args)...); + (i->*event_ptr).bubble.Raise(event_args); + if (event_args.IsHandled()) break; + } + } + + // direct + for (auto i : receive_list) { + EventArgs event_args(i, original_sender, std::forward<Args>(args)...); + (i->*event_ptr).direct.Raise(event_args); + } +} + +std::list<Control*> GetAncestorList(Control* control) { + std::list<Control*> l; + while (control != nullptr) { + l.push_front(control); + control = control->GetParent(); + } + return l; +} + +Control* FindLowestCommonAncestor(Control* left, Control* right) { + if (left == nullptr || right == nullptr) return nullptr; + + auto&& left_list = GetAncestorList(left); + auto&& right_list = GetAncestorList(right); + + // the root is different + if (left_list.front() != right_list.front()) return nullptr; + + // find the last same control or the last control (one is ancestor of the + // other) + auto left_i = left_list.cbegin(); + auto right_i = right_list.cbegin(); + while (true) { + if (left_i == left_list.cend()) return *(--left_i); + if (right_i == right_list.cend()) return *(--right_i); + if (*left_i != *right_i) return *(--left_i); + ++left_i; + ++right_i; + } +} +} // namespace + LRESULT __stdcall GeneralWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { auto window = WindowManager::GetInstance()->FromHandle(hWnd); diff --git a/src/ui/window.hpp b/src/ui/window.hpp index 7a28c257..3e0422b1 100644 --- a/src/ui/window.hpp +++ b/src/ui/window.hpp @@ -5,7 +5,7 @@ #include <memory> #include "system_headers.hpp" -#include "control.hpp" +#include "content_control.hpp" #include "events/ui_event.hpp" #include "window_class.hpp" @@ -230,13 +230,6 @@ class Window final : public ContentControl { bool window_focus_ = false; Control* focus_control_ = this; // "focus_control_" can't be nullptr - Control* mouse_capture_control_ = nullptr; - - bool is_layout_invalid_ = false; - -#ifdef CRU_DEBUG_LAYOUT - bool debug_layout_ = false; -#endif }; } // namespace cru::ui diff --git a/src/util/format.hpp b/src/util/format.hpp index 874c5b43..7c1cee05 100644 --- a/src/util/format.hpp +++ b/src/util/format.hpp @@ -5,26 +5,29 @@ namespace cru::util { namespace details { -constexpr StringView PlaceHolder(type_tag<String>) { return StringView(L"{}"); } +template <typename T> +struct TypeTag {}; -constexpr MultiByteStringView PlaceHolder(type_tag<MultiByteString>) { +constexpr StringView PlaceHolder(TypeTag<String>) { return StringView(L"{}"); } + +constexpr MultiByteStringView PlaceHolder(TypeTag<MultiByteString>) { return MultiByteStringView("{}"); } template <typename TString> void FormatInternal(TString& string) { - const auto find_result = string.find(PlaceHolder(type_tag<TString>{})); + const auto find_result = string.find(PlaceHolder(TypeTag<TString>{})); if (find_result != TString::npos) throw std::invalid_argument("There is more placeholders than args."); } template <typename TString, typename T, typename... TRest> void FormatInternal(TString& string, const T& arg, const TRest&... args) { - const auto find_result = string.find(PlaceHolder(type_tag<TString>{})); + const auto find_result = string.find(PlaceHolder(TypeTag<TString>{})); if (find_result == TString::npos) throw std::invalid_argument("There is less placeholders than args."); - string.replace(find_result, 2, FormatToString(arg, type_tag<TString>{})); + string.replace(find_result, 2, FormatToString(arg, TypeTag<TString>{})); FormatInternal<TString>(string, args...); } } // namespace details @@ -43,13 +46,13 @@ MultiByteString Format(const MultiByteStringView& format, const T&... args) { return result; } -#define CRU_FORMAT_NUMBER(type) \ - inline String FormatToString(const type number, type_tag<String>) { \ - return std::to_wstring(number); \ - } \ - inline MultiByteString FormatToString(const type number, \ - type_tag<MultiByteString>) { \ - return std::to_string(number); \ +#define CRU_FORMAT_NUMBER(type) \ + inline String FormatToString(const type number, details::TypeTag<String>) { \ + return std::to_wstring(number); \ + } \ + inline MultiByteString FormatToString(const type number, \ + details::TypeTag<MultiByteString>) { \ + return std::to_string(number); \ } CRU_FORMAT_NUMBER(int) @@ -65,30 +68,33 @@ CRU_FORMAT_NUMBER(double) #undef CRU_FORMAT_NUMBER -inline StringView FormatToString(const String& string, type_tag<String>) { +inline StringView FormatToString(const String& string, + details::TypeTag<String>) { return string; } inline MultiByteString FormatToString(const MultiByteString& string, - type_tag<MultiByteString>) { + details::TypeTag<MultiByteString>) { return string; } -inline StringView FormatToString(const StringView& string, type_tag<String>) { +inline StringView FormatToString(const StringView& string, + details::TypeTag<String>) { return string; } inline MultiByteStringView FormatToString(const MultiByteStringView& string, - type_tag<MultiByteString>) { + details::TypeTag<MultiByteString>) { return string; } -inline StringView FormatToString(const wchar_t* string, type_tag<String>) { +inline StringView FormatToString(const wchar_t* string, + details::TypeTag<String>) { return StringView(string); } inline MultiByteStringView FormatToString(const char* string, - type_tag<MultiByteString>) { + details::TypeTag<MultiByteString>) { return MultiByteString(string); } } // namespace cru::util |