温馨提示
本文最后更新于 天前,其中的信息可能已经有所发展或是发生改变。
该容器类的作用
该容器类用于在传值时包裹数据,当数据不为空值时可以调用ifTrueDo函数传入lambda,lambda函数可以接受当前ValueContainer包裹的数据作为参数传递,你可以使用ValueContainer的链式调用方法来链式调用各种数据
#pragma once
#include <QString>
#include <functional>
#include <type_traits>
#include <optional>
template<typename V>
class ValueContainer {
private:
//test
std::optional<V> v;
QString reason;
public:
ValueContainer(V value){
if constexpr (std::is_pointer_v<V>) {
v = value ? std::make_optional(value) : std::nullopt; // 如果 V 是指针类型,检查是否为 nullptr
} else {
v = std::make_optional(std::move(value)); // 对于非指针类型,直接存储值
}
}
ValueContainer() = default;
// 移动构造函数
ValueContainer(ValueContainer&& other) noexcept
: v(std::move(other.v)), reason(std::move(other.reason)) {
other.v.has_value() ? other.v.reset() : void(); // 清空源对象的值
}
// 移动赋值运算符
ValueContainer& operator=(ValueContainer&& other) noexcept {
if (this != &other) {
v = std::move(other.v);
reason = std::move(other.reason);
other.v.has_value() ? other.v.reset() : void(); // 清空源对象的值
}
return *this;
}
// 禁用拷贝构造函数和拷贝赋值运算符
operator bool() const {
if constexpr (std::is_pointer_v<V>) { // 仅当 V 是指针类型时应用
return v.has_value() && v.value() != nullptr;
}
else {
return v.has_value();
}
}
operator V() const {
return v.value();
}
void setReason(QString reason) {
this->reason = std::move(reason);
}
void setValue(V value) {
v = std::move(value);
}
bool isEmpty() const {
if constexpr (std::is_pointer_v<V>) {
return !v.has_value() || v.value() == nullptr;
}
else {
return !v.has_value();
}
}
/// <summary>
/// 当有值时执行 lambda 函数
/// </summary>
/// <typeparam name="F">传入的执行方法</typeparam>
/// <param name="lambda">传入的执行方法</param>
/// <returns>自动返回或者不返回在内部处理</returns>
template<typename F>
auto ifTrueDo(F lambda) -> std::invoke_result_t<F, V&> {
using ReturnType = std::invoke_result_t<F, V&>;
if (v.has_value()) {
return lambda(*v);
}
if constexpr (!std::is_void_v<ReturnType>) {
return ReturnType{};
}
}
template<typename F1, typename F2>
auto execute(F1 ifHasValue, F2 ifNoValue) -> std::invoke_result_t<F1, V&> {
using ReturnType = std::invoke_result_t<F1, V&>;
if (v.has_value()) {
return ifHasValue(*v);
}
else {
ifNoValue();
if constexpr (!std::is_void_v<ReturnType>) {
return ReturnType{};
}
}
}
V getValue() const {
return v.value();
}
V getValue(V defalt) const {
return v.value_or(defalt);
}
V getValue(std::function<V()> lambda) const {
return v.has_value() ? *v : lambda();
}
V&& moveValue() {
return std::move(v.value());
}
QString getReason() const {
return reason;
}
/// <summary>
/// 对容器中的值进行转换,并返回一个新的 ValueContainer。
/// 如果当前容器为空,则返回一个空的 ValueContainer。
/// </summary>
/// <typeparam name="F">转换函数类型</typeparam>
/// <returns>包含转换后值的新 ValueContainer</returns>
template<typename F>
auto map(F lambda)&& { // 注意这里是右值引用,实现零拷贝
using ResultType = std::invoke_result_t<F, V&>;
if (v.has_value()) {
return ValueContainer<ResultType>(lambda(*v));
}
else {
ValueContainer<ResultType> newContainer;
newContainer.setReason(reason); // 传递reason
return newContainer;
}
}
/// <summary>
/// 对容器中的值进行转换,并返回一个新的 ValueContainer。
/// 如果当前容器为空,则返回一个空的 ValueContainer。
/// </summary>
/// <typeparam name="F">转换函数类型</typeparam>
/// <returns>包含转换后值的新 ValueContainer</returns>
template<typename F>
auto map(F lambda) const& {
using ResultType = std::invoke_result_t<F, const V&>;
if (v.has_value()) {
return ValueContainer<ResultType>(lambda(*v));
}
else {
ValueContainer<ResultType> newContainer;
newContainer.setReason(reason);
return newContainer;
}
}
template<typename F>
auto flatMap(F lambda)&& {
using InnerContainerType = std::invoke_result_t<F, V&>;
static_assert(std::is_constructible_v<InnerContainerType, InnerContainerType&&>, "Lambda for flatMap must return a movable ValueContainer.");
if (v.has_value()) {
return lambda(*v);
}
else {
using ResultType = typename InnerContainerType::value_type;
ValueContainer<ResultType> newContainer;
newContainer.setReason(reason);
return newContainer;
}
}
using value_type = V;
// flatMap 的 const 左值引用重载 (你已有的)
template<typename F>
auto flatMap(F lambda) const& {
using InnerContainerType = std::invoke_result_t<F, const V&>;
static_assert(std::is_constructible_v<InnerContainerType, InnerContainerType&&>, "Lambda for flatMap must return a movable ValueContainer.");
if (v.has_value()) {
return lambda(*v);
}
else {
using ResultType = typename InnerContainerType::value_type;
ValueContainer<ResultType> newContainer;
newContainer.setReason(reason);
return newContainer;
}
}
/// <summary>
/// 当有值时执行 lambda 函数,并返回当前对象。
/// </summary>
/// <typeparam name="F">lambda函数</typeparam>
/// <param name="lambda">lambda函数</param>
/// <returns>返回自身</returns>
template<typename F>
auto tap(F lambda)&& {
if (v.has_value()) {
lambda(*v);
}
return std::move(*this);
}
template<typename F>
auto tap(F lambda) const& {
if (v.has_value()) {
lambda(*v);
}
return *this;
}
template<typename F>
auto tap(F lambda)& {
if (v.has_value()) {
lambda(*v);
}
return *this;
}
};具体代码
map方法用于返回处理后的新的数据类型使用VC包裹,flatmap函数将lambda内部返回VC变量展开重新返回展开后的VC变量,tap函数用于处理数据并返回自身,其他方法由数据名即可看出作用
希望我的博客能够对你有帮助

评论
评论区还没开放,部署评论服务后就能留言啦~