【问题标题】:Verbatim stringify逐字字符串化
【发布时间】:2015-09-16 09:57:54
【问题描述】:

是否可以调整常见的 C++ 字符串化方法:

template<typename T> 
std::string Stringify(T const &value) 
{
    std::stringstream ss;
    ss << value;
    return ss.str();
}

以便打印实际值而不是值的截断或科学记数法表示,例如:

std::cout << Stringify(std::numeric_limits<float>::max()) << std::endl;

不应该打印3.40282e+38,而是3'402'82...(我只是没有提到其余的数字,我并不是在暗示应该打印点)

【问题讨论】:

  • 您在寻找setprecision吗? @Sneftel 那不处理,例如,0.0000001。
  • @T.C.我最初的想法是使用它,但问题是setprecision 是什么?我的意思是这需要是动态的和自我调节的

标签: c++


【解决方案1】:

是的,将您想要的操纵器添加到函数签名并将它们转发到流。

template<typename T, typename Manip> 
std::string Stringify(T const &value, Manip manip) 
{
    std::stringstream ss;
    ss << manip << value;
    return ss.str();
}

附上示例代码;

int main()
{
    using namespace std;
    // The precision here is set to be sufficient to print the test platform
    cout << Stringify(numeric_limits<float>::max(), setprecision(50)) << endl;
}    

我假设将使用多个操纵器。为此,可以为所需数量的操纵器添加函数重载,或者您可以使用(使用 C++11)可变参数模板和完美转发。

template <typename Stream>
Stream& AddManip(Stream& str)
{
    // end the recursion
    return str;
}

template <typename Stream, typename Head, typename... Tails>
Stream& AddManip(Stream& str, Head&& head, Tails&&... tails)
{
    // add the head manipulator and forward the rest
    str << std::forward<Head>(head);
    return AddManip(str, std::forward<Tails>(tails)...);
}

template<typename T, typename... Manip> 
std::string Stringify(T const &value, Manip&&... manip) 
{
    std::stringstream ss;
    // add the manipulators to the stream
    AddManip(ss, std::forward<Manip>(manip)...);
    ss << value;
    return ss.str();
}

int main()
{
    using namespace std;
    cout << Stringify(numeric_limits<int>::max(), setprecision(40), std::hex) << endl;
}    

【讨论】:

    【解决方案2】:

    我知道宏是邪恶的,但我在我的作品中做了一两个例外。其中之一是this macro:

    #include <sstream>
    
    #define SSTR( x ) static_cast< std::ostringstream & >( \
            ( std::ostringstream() << std::dec << x ) ).str()
    

    Detailed explanation available.

    这种结构的一个优点是可以轻松内联操纵器:

     std::string str = SSTR( "numeric_limits<float>::max is: "
                           << setprecision(50)
                           << numeric_limits<float>::max()
                           );
    

    另一个好处是它很紧凑,而且相当 C++98。

    缺点是它是一个宏。 ;-)

    【讨论】:

    • 有趣的是consistenty faster,而不是我在问题中提到的流行方法。 c++11 的替代品是 faster though 。输出保持不变,但我仍然无法以这种方式自动调整精度。我还 +1 链接的答案,因为我喜欢这个博客
    • @NikosAthanasiou:我怀疑编译器可以围绕临时的ostringstream 对象进行一些优化,但从未费心对其进行实际基准测试。 (我对SSTR() 的主要用途是将异常消息拼凑在一起,此时性能仍然是次要的。)至于自动精度,您可以将setprecision 添加到宏中。 .. 但无论如何,感谢您的反馈!
    • @NikosAthanasiou:我冒昧地将您的基准添加到我的主页。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 2017-03-18
    相关资源
    最近更新 更多