LeviLamina icon indicating copy to clipboard operation
LeviLamina copied to clipboard

[Bug] `mce::UUID` 在反射中被当作 `std::string` 处理

Open engsr6982 opened this issue 1 month ago • 2 comments

Describe the bug

我希望将 json 数据反射到 std::unordered_set<mce::UUID> 容器内,但是构建失败。

我特化了 UUID 的 deserialize 但是它不工作,反射系统依旧将 mce::UUID 视为 string 处理,但是 mce::UUID 并没有有效的 operator= 可以从 std::string 赋值,导致构建失败。

最小可复现代码:

#include "ll/api/reflection/Deserialization.h"
#include "ll/api/reflection/Reflection.h"
#include "ll/api/reflection/Serialization.h"
#include "mc/platform/UUID.h"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"
#include <type_traits>

namespace mce {

template <class T, class J>
inline ll::Expected<> deserialize(T& uuid, J const& j) noexcept
    requires(std::same_as<T, UUID>)
{
    if (j.is_string()) {
        if (auto res = UUID::fromString((std::string const&)j); res != UUID::EMPTY()) {
            uuid = res;
            return {};
        }
        return ll::makeStringError("invalid uuid");
    }
    return ll::makeStringError("field must be a string");
}

} // namespace mce

namespace plotx {

void test() {
    std::unordered_set<mce::UUID> data;

    nlohmann::ordered_json j{};
    ll::reflection::deserialize(data, j).value(); // Clangd: In template: no viable overloaded '='

    static_assert(!ll::traits::is_string_v<mce::UUID>, "UUID should NOT be string-like"); // false
}

}
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): error C2679: 二元“=”: 没有找到接受“std::string”类型的右操作数的运算符(或没有可接受的转换)
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\mc/platform/UUID.h(57): note: 可能是“mce::UUID &mce::UUID::operator =(mce::UUID &&)”
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: “mce::UUID &mce::UUID::operator =(mce::UUID &&)”: 无法将参数 2 从“std::string”转换为“mce::UUID &&”
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: 原因如下: 无法从“std::string”转换为“mce::UUID”
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: 没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\mc/platform/UUID.h(57): note: 或    “mce::UUID &mce::UUID::operator =(const mce::UUID &)”
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: “mce::UUID &mce::UUID::operator =(const mce::UUID &)”: 无法将参数 2 从“std::string”转换为“const mce::UUID &”
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: 原因如下: 无法从“std::string”转换为“const mce::UUID”
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: 没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: 尝试匹配参数列表“(T, std::string)”时
        with
        [
            T=ll::reflection::deserialize_impl::value_type
        ]
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(88): note: 模板实例化上下文(最早的实例化上下文)为
D:\Project\PlotX\src\plotx\core\PlotRegistry.cc(41): note: 查看对正在编译的函数 模板 实例化“nonstd::expected_lite::expected<void,ll::Error> ll::reflection::deserialize<std::unordered_set<mce::UUID,std::hash<mce::UUID>,std::equal_to<mce::UUID>,std::allocator<mce::UUID>>,nlohmann::json_abi_v3_11_3::ordered_json&>(T &,J) noexcept”的引用
        with
        [
            T=std::unordered_set<mce::UUID,std::hash<mce::UUID>,std::equal_to<mce::UUID>,std::allocator<mce::UUID>>,
            J=nlohmann::json_abi_v3_11_3::ordered_json &
        ]
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(43): note: 查看对正在编译的函数 模板 实例化“nonstd::expected_lite::expected<void,ll::Error> ll::reflection::deserialize_impl<std::unordered_set<mce::UUID,std::hash<mce::UUID>,std::equal_to<mce::UUID>,std::allocator<mce::UUID>>,nlohmann::json_abi_v3_11_3::ordered_json&>(T &,J,ll::meta::PriorityTag<2>)”的引用
        with
        [
            T=std::unordered_set<mce::UUID,std::hash<mce::UUID>,std::equal_to<mce::UUID>,std::allocator<mce::UUID>>,
            J=nlohmann::json_abi_v3_11_3::ordered_json &
        ]
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(130): note: 查看对正在编译的函数 模板 实例化“nonstd::expected_lite::expected<void,ll::Error> ll::reflection::deserialize<ll::reflection::deserialize_impl::value_type,nlohmann::json_abi_v3_11_3::ordered_json&>(T &,J) noexcept”的引用
        with
        [
            T=ll::reflection::deserialize_impl::value_type,
            J=nlohmann::json_abi_v3_11_3::ordered_json &
        ]
C:\Users\x\AppData\Local\.xmake\packages\l\levilamina\1.4.1\9b537f9b4c15422cbb569116af03d7f3\include\ll/api/reflection/Deserialization.h(43): note: 查看对正在编译的函数 模板 实例化“nonstd::expected_lite::expected<void,ll::Error> ll::reflection::deserialize_impl<ll::reflection::deserialize_impl::value_type,nlohmann::json_abi_v3_11_3::ordered_json&>(T &,J,ll::meta::PriorityTag<4>)”的引用
        with
        [
            T=ll::reflection::deserialize_impl::value_type,
            J=nlohmann::json_abi_v3_11_3::ordered_json &
        ]
ninja: build stopped: subcommand failed.

To Reproduce

如上

Expected behavior

正常反射

Screenshots

No response

Platform

win10

Version

1.4.1

Additional context

No response

engsr6982 avatar Nov 23 '25 08:11 engsr6982