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

C++23中能否用std::print输出自定义对象?编译报错求解

C++23中使用std::print输出自定义对象的编译问题解决

问题场景

在C++23标准下尝试通过std::print输出自定义Person对象,编写了特化的std::formatter模板,但编译报错,提示类型不可格式化。

原代码示例

#include <iostream>
#include <string>
#include <format>  

struct Person {
    std::string name;
    int age;
};


template <>
struct std::formatter<Person> : std::formatter<std::string> {
   
    auto format(const Person& p, std::format_context& ctx) {
        return std::format_to(ctx.out(), "Name: {}, Age: {}", p.name, p.age);
    }
};

int main() {
    Person p1{"Alice", 32};

    std::cout << std::format("{}", p1) << std::endl;  

    std::print("{}\n", p1); 

    return 0;
}

编译错误信息

/opt/compiler-explorer/clang-trunk-20250119/bin/../include/c++/v1/__format/format_arg_store.h:168:17:
error: static assertion failed due to requirement '__arg != __arg_t::__none': the supplied type is not formattable   168 |   static_assert(__arg != __arg_t::__none, "the supplied type is not formattable");
|                 ^~~~~~~~~~~~~~~~~~~~~~~~ /opt/compiler-explorer/clang-trunk-20250119/bin/../include/c++/v1/__format/format_arg_store.h:214:54:
note: in instantiation of function template specialization 'std::__format::__create_format_arg<std::format_context, Person>' requested here   214 |         basic_format_arg<_Context> __arg = __format::__create_format_arg<_Context>(__args);
|

问题原因与解决方法

问题出在继承std::formatter<std::string>的实现方式上。libc++的实现对formatter特化有严格要求,需要完全符合std::formattable概念——必须显式实现parse方法,或确保特化的模板能被正确识别为可格式化类型。

正确的实现方式是直接定义std::formatter<Person>,并实现parse和format方法:

#include <iostream>
#include <string>
#include <format>  

struct Person {
    std::string name;
    int age;
};

template <>
struct std::formatter<Person> {
    // 解析格式说明符:此处无需自定义格式,直接返回上下文结束迭代器
    constexpr auto parse(std::format_parse_context& ctx) {
        return ctx.end();
    }

    // 格式化自定义对象:将Person转为指定格式并写入输出迭代器
    auto format(const Person& p, std::format_context& ctx) const {
        return std::format_to(ctx.out(), "Name: {}, Age: {}", p.name, p.age);
    }
};

int main() {
    Person p1{"Alice", 32};

    std::cout << std::format("{}", p1) << std::endl;  
    std::print("{}\n", p1); 

    return 0;
}

解释

  • parse方法:负责解析格式字符串中的自定义说明符,这里不需要额外格式控制,直接返回ctx.end()即可。
  • format方法:核心逻辑,将Person对象的内容格式化为指定字符串,通过std::format_to写入上下文的输出迭代器。

修改后,std::format和std::print都能正确识别Person类型为可格式化类型,编译通过并正常输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:34:55