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

如何为模板类内的结构体创建std::formatter以支持std::print?

问题描述

我需要为模板类ThreeStack中定义的StackProperties结构体实现std::formatter,这样就能用std::print打印该结构体的实例。

我的ThreeStack类代码如下:

template <typename ValueType, std::size_t SizeOfEachStack> requires (SizeOfEachStack > 0)
class ThreeStack
{
public:
    struct StackProperties
    {
        std::size_t min_index{0};
        std::size_t max_index{0};
        std::size_t current_index{0};
    };

    ThreeStack()
    {
        for(std::size_t stack_number = 0; stack_number < num_of_stacks; stack_number++)
        {
            stack_properties.at(stack_number).min_index = stack_number * SizeOfEachStack;
            stack_properties.at(stack_number).current_index = stack_properties.at(stack_number).min_index;
            stack_properties.at(stack_number).max_index = stack_properties.at(stack_number).min_index + SizeOfEachStack - 1;
        }
    };

    // Print function to print the internal arrays.
    void print_internal_arrays()
    {
        for(std::size_t stack_number = 0; stack_number < num_of_stacks; stack_number++)
        {
            std::print("Stack {}: {}\n", stack_number, stack_properties.at(stack_number));
        }
    }

private:
    static constexpr size_t num_of_stacks{3};
    std::array<ThreeStack::StackProperties, num_of_stacks> stack_properties{};
};

我尝试编写的std::formatter无法正常工作:

// Create a std::formatter for the ThreeStack::StackProperties struct for any ThreeStack<ValueType, SizeOfEachStack>.
template <typename ValueType, std::size_t SizeOfEachStack>
struct std::formatter<ThreeStack<ValueType, SizeOfEachStack>::StackProperties>
{
    constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }

    template <typename FormatContext>
    auto format(const ThreeStack<ValueType, SizeOfEachStack>::StackProperties& stack_properties, FormatContext& ctx)
    {
        return format_to(ctx.out(), "min_index: {}, max_index: {}, current_index: {}", stack_properties.min_index, stack_properties.max_index, stack_properties.current_index);
    }
};

编译时出现以下错误:

<source>:43:78: error: type/value mismatch at argument 1 in template parameter list for 'template<class _Tp, class _CharT> struct std::formatter'
   43 | struct std::formatter<ThreeStack<ValueType, SizeOfEachStack>::StackProperties>
      |                                                                              ^
<source>:43:78: note:   expected a type, got 'ThreeStack<ValueType, SizeOfEachStack>::StackProperties'
<source>:43:13: error: template class without a name
   43 | struct std::formatter<ThreeStack<ValueType, SizeOfEachStack>::StackProperties>
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compiler returned: 1
解决方案

编译错误的核心原因是:在模板参数中使用ThreeStack<ValueType, SizeOfEachStack>::StackProperties时,编译器无法确定这是一个类型(它可能被解析为值或成员),需要用typename关键字显式声明这是一个类型。另外,std::formatter本身是双模板参数结构体(第二个参数默认是char),需要匹配其完整模板参数列表。

修正后的std::formatter实现

template <typename ValueType, std::size_t SizeOfEachStack, typename CharT>
struct std::formatter<typename ThreeStack<ValueType, SizeOfEachStack>::StackProperties, CharT>
{
    constexpr auto parse(std::format_parse_context& ctx) {
        auto it = ctx.begin();
        if (it != ctx.end() && *it != '}') {
            throw std::format_error("invalid format for StackProperties");
        }
        return it;
    }

    template <typename FormatContext>
    auto format(const typename ThreeStack<ValueType, SizeOfEachStack>::StackProperties& props, FormatContext& ctx)
    {
        return std::format_to(ctx.out(),
            "min_index: {}, max_index: {}, current_index: {}",
            props.min_index, props.max_index, props.current_index);
    }
};

关键修正点

  • 添加typename关键字:typename ThreeStack<ValueType, SizeOfEachStack>::StackProperties明确告诉编译器这是一个类型,解决"type/value mismatch"错误。
  • 匹配完整模板参数:std::formatter的第二个模板参数是字符类型(默认char),将其加入模板参数列表,保证特化的正确性。
  • 完善parse方法:正确处理格式字符串解析,避免非法格式导致的未定义行为。

完整可编译代码示例

#include <iostream>
#include <format>
#include <array>

template <typename ValueType, std::size_t SizeOfEachStack> requires (SizeOfEachStack > 0)
class ThreeStack
{
public:
    struct StackProperties
    {
        std::size_t min_index{0};
        std::size_t max_index{0};
        std::size_t current_index{0};
    };

    ThreeStack()
    {
        for(std::size_t stack_number = 0; stack_number < num_of_stacks; stack_number++)
        {
            stack_properties.at(stack_number).min_index = stack_number * SizeOfEachStack;
            stack_properties.at(stack_number).current_index = stack_properties.at(stack_number).min_index;
            stack_properties.at(stack_number).max_index = stack_properties.at(stack_number).min_index + SizeOfEachStack - 1;
        }
    };

    void print_internal_arrays()
    {
        for(std::size_t stack_number = 0; stack_number < num_of_stacks; stack_number++)
        {
            std::print("Stack {}: {}\n", stack_number, stack_properties.at(stack_number));
        }
    }

private:
    static constexpr size_t num_of_stacks{3};
    std::array<ThreeStack::StackProperties, num_of_stacks> stack_properties{};
};

template <typename ValueType, std::size_t SizeOfEachStack, typename CharT>
struct std::formatter<typename ThreeStack<ValueType, SizeOfEachStack>::StackProperties, CharT>
{
    constexpr auto parse(std::format_parse_context& ctx) {
        auto it = ctx.begin();
        if (it != ctx.end() && *it != '}') {
            throw std::format_error("invalid format for StackProperties");
        }
        return it;
    }

    template <typename FormatContext>
    auto format(const typename ThreeStack<ValueType, SizeOfEachStack>::StackProperties& props, FormatContext& ctx)
    {
        return std::format_to(ctx.out(),
            "min_index: {}, max_index: {}, current_index: {}",
            props.min_index, props.max_index, props.current_index);
    }
};

int main() {
    ThreeStack<int, 5> stack;
    stack.print_internal_arrays();
    return 0;
}

这段代码编译后会输出:

Stack 0: min_index: 0, max_index: 4, current_index: 0
Stack 1: min_index: 5, max_index: 9, current_index: 5
Stack 2: min_index: 10, max_index: 14, current_index: 10

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:56:10