You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS clang++下boost::json tag_invoke转换time_point编译错误求助

问题描述

环境:macOS clang++ 15.0.0

尝试用tag_invoke()实现boost::json::value与std::chrono::time_point之间的转换,代码如下:

#include <chrono>
#include <iostream>
#include <sstream>
#include <string>

#include <boost/json.hpp>

#include "date.h"  // Howard Hinnant's date library, until <chrono> supports parse().


using Time = std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>;


Time tag_invoke(boost::json::value_to_tag<Time>&, const boost::json::value& jv)
{
    Time t;

    std::istringstream ss{value_to<std::string>(jv)};
    ss >> date::parse("%FT%T%Z", t);
  
    return t;
}


int main()
{
    boost::json::value jv = boost::json::parse(R"({"time": "1970-01-01T00:00:00.000000001Z"})";

    Time t = value_to<Time>(jv);

    std::cout << t.time_since_epoch().count() << '\n';

    return 0;
}

编译时报错No suitable tag_invoke overload found for the type,完整错误信息:

/usr/local/include/boost/json/detail/value_to.hpp:845:5: error: static assertion failed due to requirement '!std::is_same<std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000000000>>>, std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000000000>>>>::value': No suitable tag_invoke overload found for the type
    static_assert(
    ^
/usr/local/include/boost/json/value_to.hpp:96:20: note: in instantiation of function template specialization 'boost::json::detail::value_to_impl<std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000000000>>>, boost::json::detail::no_context>' requested here
    return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx );
                   ^
/usr/local/include/boost/json/value_to.hpp:148:12: note: in instantiation of function template specialization 'boost::json::value_to<std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000000000>>>, boost::json::detail::no_context>' requested here
    return value_to<T>( jv, detail::no_context() );
           ^
src/tag_invoke.cpp:29:14: note: in instantiation of function template specialization 'boost::json::value_to<std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long, std::ratio<1, 1000000000>>>>' requested here
    Time t = value_to<Time>(jv);

封装为普通函数Time parse_time(...)可正常运行,但使用tag_invoke()则报错。

问题分析与解决

1. 语法错误修正

main函数中boost::json::parse的字符串末尾缺少右括号,导致基础语法错误,修正后:

boost::json::value jv = boost::json::parse(R"({"time": "1970-01-01T00:00:00.000000001Z"})");

2. ADL查找失败问题

Boost.JSON的value_to依赖**参数依赖查找(ADL)**定位tag_invoke重载。你的Time是全局命名空间下的typedef,tag_invoke也定义在全局命名空间,无法被ADL正确识别。有两种解决方式:

  • 方式一:将tag_invoke放入boost::json命名空间
    扩展Boost.JSON命名空间,将重载放入其中,确保内部逻辑能找到:
    namespace boost::json {
    Time tag_invoke(value_to_tag<Time>&, const value& jv)
    {
        Time t;
        std::istringstream ss{value_to<std::string>(jv)};
        ss >> date::parse("%FT%T%Z", t);
        return t;
    }
    } // namespace boost::json
    
  • 方式二:将类型与tag_invoke放入自定义命名空间
    把Time和对应的tag_invoke重载放在同一个自定义命名空间,利用ADL规则让编译器找到:
    namespace my_time {
    using Time = std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>;
    
    Time tag_invoke(boost::json::value_to_tag<Time>&, const boost::json::value& jv)
    {
        Time t;
        std::istringstream ss{boost::json::value_to<std::string>(jv)};
        ss >> date::parse("%FT%T%Z", t);
        return t;
    }
    } // namespace my_time
    
    后续main函数中使用my_time::Time即可。

3. JSON对象访问错误

当前代码直接将整个JSON对象({"time": "..."})传给value_to<Time>,但你的tag_invoke期望处理JSON字符串值,需提取对应字段:

Time t = value_to<Time>(jv.at("time"));
修正后的完整代码
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>

#include <boost/json.hpp>

#include "date.h"  // Howard Hinnant's date library, until <chrono> supports parse().

using Time = std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>;

namespace boost::json {
Time tag_invoke(value_to_tag<Time>&, const value& jv)
{
    Time t;
    std::istringstream ss{value_to<std::string>(jv)};
    ss >> date::parse("%FT%T%Z", t);
    return t;
}
} // namespace boost::json

int main()
{
    boost::json::value jv = boost::json::parse(R"({"time": "1970-01-01T00:00:00.000000001Z"})");

    Time t = boost::json::value_to<Time>(jv.at("time"));

    std::cout << t.time_since_epoch().count() << '\n';

    return 0;
}

内容的提问来源于stack exchange,提问作者John Duffy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 22:50:31