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

如何用C++折叠表达式实现带分隔符的可变参数打印?

用折叠表达式实现带分隔符的可变参数模板打印函数

问题描述

尝试用折叠表达式替代模板递归编写可变参数模板打印函数,当前代码:

template <typename... Ts, typename charT, typename traits>
constexpr std::basic_ostream<charT, traits>& many_print(std::basic_ostream<charT, traits>& os, Ts... args){
  os << '{';
  (os << ... << args);
  return os << '}';
}

调用many_print(std::cout, 1, 2);时输出{12},期望输出{1, 2}。

尝试过的写法会导致分隔符前置:

template <typename... Ts, typename charT, typename traits>
constexpr std::basic_ostream<charT, traits>& many_print(std::basic_ostream<charT, traits>& os, Ts... args){
  os << '{';
  (os << ... << ((void)(os << ", "), args));
  return os << '}';
}

输出为{, 1, 2},不符合需求。需要无需模板递归的解决方案,哪怕能输出{1, 2, }也可接受。


解决方案

1. 完美无末尾分隔符的实现(推荐)

结合折叠表达式和lambda表达式,通过标记是否为第一个参数来控制分隔符输出,逻辑清晰且无递归:

#include <iostream>
#include <utility> // 用于std::forward

template <typename... Ts, typename charT, typename traits>
constexpr std::basic_ostream<charT, traits>& many_print(std::basic_ostream<charT, traits>& os, Ts&&... args){
  os << '{';
  bool is_first = true;
  
  // 定义lambda处理单个参数的打印,自动处理分隔符
  auto print_arg = [&](auto&& arg) {
    if (!is_first) {
      os << ", ";
    }
    is_first = false;
    os << std::forward<decltype(arg)>(arg);
  };
  
  // 用折叠表达式遍历所有参数,调用lambda打印
  (print_arg(std::forward<Ts>(args)), ...);
  
  return os << '}';
}

// 处理无参数的重载版本
template <typename charT, typename traits>
constexpr std::basic_ostream<charT, traits>& many_print(std::basic_ostream<charT, traits>& os){
  return os << "{}";
}

调用示例:

int main() {
  many_print(std::cout, 1, "hello", 3.14); // 输出 {1, hello, 3.14}
  many_print(std::cout); // 输出 {}
  return 0;
}

2. 允许末尾带分隔符的简化实现

如果可以接受末尾的逗号,写法更简洁:

template <typename... Ts, typename charT, typename traits>
constexpr std::basic_ostream<charT, traits>& many_print(std::basic_ostream<charT, traits>& os, Ts&&... args){
  os << '{';
  // 右折叠打印每个参数+逗号
  (os << ... << (std::forward<Ts>(args) << ", "));
  return os << '\b}'; // 用退格符去掉最后一个逗号(仅终端输出有效)
  // 若无需去除末尾逗号,直接 return os << '}'; 即可,输出如 {1, 2, }
}

注意:退格符\b仅在终端输出时能覆盖末尾逗号,若输出到文件或其他流,建议直接保留末尾逗号,或者结合if constexpr处理空参数情况。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:40:29