使用Boost Karma将std :: stringstream替换为double到std :: string的转换

DiB*_*DiB 2 c++ performance std boost-spirit

为了提高性能,我希望更换:

template<class T> std::string ToStringFixed(const T x, const unsigned int width = 8)
{
  std::stringstream ss;
  ss << std::setprecision(width) << std::fixed << x;
  return ss.str();
}
Run Code Online (Sandbox Code Playgroud)

有了Boost Karma的实现,因为我们的项目已经使用了Boost,它看起来比上面的天真解决方案有显着的性能提升.

就像是:

std::string ToString(double d)
{
  using boost::spirit::karma::double_;
  using boost::spirit::ascii::space;
  using boost::spirit::karma::generate;

  std::string s
  std::back_insert_iterator<std::string> sink(s);
  generate(sink, double_, d);
  return s;
}
Run Code Online (Sandbox Code Playgroud)

这是从以下网站采用的:http://thisthread.blogspot.com/2011/04/generating-text-with-spirit-karma.html似乎走在正确的轨道上,但我不清楚如何控制精度,或者如果这样的解决方案对于浮点类型可以是模板友好的而不使用类型特征.(通过C++ 14使用的答案是可以接受的.)

llo*_*miz 5

您可以借助real_generator格式化策略实现所需目标.由于您只需要修改可以从默认值派生的精度real_policies<Num>,然后添加precision(Num n)具有所需行为的成员函数.

在WandBox上运行

#include <iostream>
#include <string>
#include <cmath>

#include <boost/spirit/include/karma.hpp>

template <typename Num>
struct precision_policy : boost::spirit::karma::real_policies<Num>
{
    precision_policy(int prec):precision_(prec){}
    int precision(Num n) const { return precision_; }
    int precision_;
};

std::string ToStringFixedKarma(double d, const unsigned int width = 8)
{
  using boost::spirit::karma::real_generator;
  using boost::spirit::ascii::space;
  using boost::spirit::karma::generate;

  real_generator<double,precision_policy<double> > my_double_(width);

  std::string s;
  std::back_insert_iterator<std::string> sink(s);
  generate(sink, my_double_, d);
  return s;
}

int main() {
    const double pi = std::acos(-1);
    std::cout << ToStringFixedKarma(pi) << std::endl;
    std::cout << ToStringFixedKarma(pi,2) << std::endl;
    std::cout << ToStringFixedKarma(pi,4) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

PS:文档(并检查源代码)似乎暗示这些策略中的成员函数需要是静态的,这将使您所需要的东西变得不可能,但正如此示例所示,情况并非如此.