【问题标题】:Simple command to combine an arbitrary number of values of arbitrary types into a single string将任意数量的任意类型的值组合成单个字符串的简单命令
【发布时间】:2024-04-19 21:25:02
【问题描述】:

考虑下面的代码。

int id = 666;
stringstream stream(stringstream::in | stringstream::out);
stream << "Object " << id << " active.";
file.write(stream.str());

它很好地将

int id = 666;
WRITE("Object ", id, " active.");

这在 C++ 中是否可能以可移植的方式,即使使用 Boost.Preprocessor、内联函数和所有技巧。

【问题讨论】:

  • 我认为您需要更具体一些,因为就目前而言,您应该能够将原始代码包装在一个名为 WRITE 的函数中。
  • 您能否使用... 概念使您的WRITE 类似于printf
  • 所以您只想将任意数量的不同类型值放入文件中?您可以尝试使用可变参数模板。
  • 我为这个非常不清楚的问题道歉。我试图改进它,澄清我需要可变数量的参数,并且 使用 stringstream 不是强制性的。
  • 一个std::stringstream默认是开放读写的,不需要用(stringstream::in | stringstream::out)构造它

标签: c++ c-preprocessor variadic-functions boost-preprocessor


【解决方案1】:

您可以在不使用宏进行类型检查的情况下完成此操作:

//filewrite.h
#define WRITE(first, second, third) \
{\
   stringstream stream(stringstream::in | stringstream::out);\
   stream << first << second << third;\
   file.write(stream.str());\
}

或者,更简洁,使用模板函数:

template<typename T1, typename T2, typename T3>
void WRITE(T1 const& first, T2 const& second, T3 const& third, fstream& file)
{
   stringstream stream(stringstream::in | stringstream::out);
   stream << first << second << third;
   file.write(stream.str());
}

【讨论】:

  • 鉴于标题,我认为这样做的目的是不进行类型检查,因此不是函数参数中的特定类型
  • 现在有什么方法可以扩展它来满足无限数量的需求?
  • @MartyE 你可以,使用可变参数,但我现在没有时间检查语法。
  • 在使用宏时,如果在用户代码中可以使用(x &lt;&lt; y &lt;&lt; z) 表示法,也可以轻松使用无限参数。
  • 最后两个 cmets 很可能是我查询的两个正确答案。我去看看!
【解决方案2】:

如果您真的不想进行类型检查,请不要使用 C++,它是一种静态类型语言!

如果您只是想让它适用于任何类型,请使用宏 (eurgh) 或使用可变参数模板,例如 https://gitlab.com/redistd/redistd/blob/master/include/redi/printers.h,它支持:

#include <redi/printers.h>
using redi::println;
int main()
{
  int id = 666;
  println("Object ", id, " active.");  // write arguments to stdout
}

println 函数接受任意数量的参数,并且受到来自Howard Hinnant 的一些示例代码的启发,无耻地从窃取。

很容易将其改写为fstream 而不是std::cout,例如通过添加

inline
void
fprintln()
{ file << std::endl; }

template<typename T0, typename... T>
  inline
  void
  fprintln(const T0& t0, const T&... t)
  {
    print_one(file, t0);
    fprintln(t...);
  }

然后:

 fprintln("Object ", id, " active.");  // write arguments to 'file'

【讨论】:

    【解决方案3】:

    您不需要(也不想要)宏。这就是模板的设计 为:

    template <typename T>
    void
    write( std::string const& prefix, T const& value, std::string const& suffix )
    {
        std::ostringstream fmt;
        fmt << prefix << value << suffix;
        file.write( fmt.str() );
    }
    

    另一方面,何必呢?为什么不让客户端代码使用 惯用语:

    file << prefix << value << suffix;
    

    【讨论】:

      最近更新 更多