C++ C++;格式化宏/内联ostringstream

C++ C++;格式化宏/内联ostringstream,c++,format,printing,macros,ostringstream,C++,Format,Printing,Macros,Ostringstream,我正在尝试编写一个宏,它允许我执行以下操作:格式化(a您遇到的问题与操作符这是一个有效的解决方案: #define FORMAT(items) \ ((std::ostringstream&)(std::ostringstream() << std::dec << items)).str() #定义格式(项目)\ ((std::ostringstream&)

我正在尝试编写一个宏,它允许我执行以下操作:
格式化(a您遇到的问题与
操作符这是一个有效的解决方案:

#define FORMAT(items)                                                   \
   ((std::ostringstream&)(std::ostringstream() << std::dec << items)).str()
#定义格式(项目)\

((std::ostringstream&)(std::ostringstream()为什么不使用函数而不是宏?

这里有一个像cadabra这样的答案,它不会影响ostream状态:

#define FORMAT(items)     static_cast<std::ostringstream &>((std::ostringstream() << std::string() << items)).str()

#define FORMAT(items)static_cast((std::ostringstream()以下是我使用的内容。它完全适合头文件中一个整洁的类定义

更新:对代码的重大改进归功于

//makestring.h:
类生成字符串
{
公众:
std::stringstream;
运算符std::string()const{return stream.str();}
模板

MakeString&operator你们都已经很清楚这一点了。但要理解这一点有点挑战性。所以让我试着总结一下你们所说的


这里的困难在于:

  • 我们正在玩一个临时的
    ostringstream
    对象,因此禁止使用地址

  • 因为它是临时的,所以我们不能通过强制转换将其转换为
    ostream
    对象

  • 构造函数[显然]和
    str()
    都是类
    ostringstream
    方法。 (是的,我们需要使用
    .str()
    。直接使用
    ostringstream
    对象将调用
    ios::operator void*()
    ,返回一个指针,如good/bad value,而不是string对象。)


  • operator当我接受mrree的解决方案(标记为“首选”的解决方案,解释得很好的解决方案,以及适用于G++的解决方案)时,我遇到了MSVC++的问题:使用此宏生成的所有字符串最终都是空的

    几个小时后(还有很多挠头和问问题),我发现seekp()调用是罪魁祸首。我不确定MSVC++与之有什么不同,但是

    ostringstream().seekp( 0, ios_base::cur )
    
    用卡达拉的

    ostringstream() << std::dec
    

    ostringstream(),因为他想使用插入运算符,所以假设我可以手动编写N个模板函数,每个参数一个,然后使用格式(a,“b”,c,d)。或者使用coppro的解决方案来生成它们。但两者都不好看。谢谢,这是非常有用的。我没有太多使用Boost,看看里面有什么很有趣。因为临时变量不能绑定到非常量引用。例如,
    string&str=string(“hello”);
    无效。因此,
    char*
    的重载无效(和许多其他重载)没有被选中。大卫:哈。原始海报特别提到了可变模板,这就是这个令人震惊的预处理器滥用所复制的(虽然不是一半)。别误会我的意思:你回答了问题的难点部分。没有在gcc 4.0.1上编译。这里有一个不会弄乱状态,但会复制字符串。\ define FORMAT(items)\((std::ostringstream&)(std::ostringstream()您的第二个示例将为您提供一个指向已销毁的临时字符串的指针-祝您好运。我尝试了该部分,但它仍然无法编译。我已将其从我的答案中删除!感谢您的输入。无需宏:放置模板StringMaker&operator@litb:那要优雅得多。谢谢!我有updated我的答案与Lynice的工作一致。请注意,如果字符串仅在表达式期间使用,则可以安全地隐式生成C样式的字符串。请参见dribeas在此处的密切相关工作:std::dec告诉流将数字呈现为基数10或十进制。它使用一个成员格式化程序,然后返回一个引用rence可以绑定到一个临时的。std::dec是一个很好的传递参数,它不会对流的输出产生副作用。
    #define MAKE_OUTPUT(z, n, data) \
        BOOST_PP_TUPLE_ELEM(2, 0, data) << BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n);
    
    #define MAKE_FORMAT(z, n, data) \
        template <BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), typename T)> \
        inline string format(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(n), T, p)) \
        { \
          ostringstream s; \
          BOOST_PP_REPEAT_##z(z, n, MAKE_OUTPUT, (s, p)); \
          return s.str(); \
        }
    
    #define FORMAT(items)                                                   \
       ((std::ostringstream&)(std::ostringstream() << std::dec << items)).str()
    
    #define FORMAT(items)     static_cast<std::ostringstream &>((std::ostringstream() << std::string() << items)).str()
    
    // makestring.h:
    
    class MakeString
    {
        public:
            std::stringstream stream;
            operator std::string() const { return stream.str(); }
    
            template<class T>
            MakeString& operator<<(T const& VAR) { stream << VAR; return *this; }
    };
    string myString = MakeString() << a << "b" << c << d;
    #define FORMAT(ITEMS)                                             \
      ( ( dynamic_cast<ostringstream &> (                             \
             ostringstream() . seekp( 0, ios_base::cur ) << ITEMS )   \
        ) . str() )
    
    ostringstream().seekp( 0, ios_base::cur )
    
    ostringstream() << std::dec