2017-02-15 36 views
2

Для повышения производительности, я ищу, чтобы заменить:Использования подталкивания Кармы заменить зЬй :: stringstream для двойного в StD :: струнного преобразования

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(); 
} 

С реализацией от повышающей кармы, как наш проект уже использует подталкивание и он, похоже, имеет значительное увеличение производительности над наивным решением выше.

Что-то вроде:

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; 
} 

который принимается от: http://thisthread.blogspot.com/2011/04/generating-text-with-spirit-karma.html, кажется, на правильном пути, но это мне не ясно, как контролировать точность, или если такое решение может быть шаблон - дружелюбно для типов с плавающей точкой без использования признаков типа. (Ответы на использование через C++ 14 приемлемы.)

+0

@NeilButterworth Насколько мне известно, std :: to_string не позволяет контролировать формат. Здесь я хочу контролировать точность. Другие функции также могут контролировать ширину вывода. Все это легко с std :: stringstream, но я хотел бы получить более ориентированное на производительность решение. – DiB

ответ

5

Вы можете достичь того, чего хотите, с помощью real_generator's formatting policies. Поскольку вам нужно только изменить точность, которую вы можете получить из значения по умолчанию real_policies<Num>, а затем добавить функцию-член precision(Num n), которая имеет нужное поведение.

Running on 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; 
} 

PS: Документация (и проверка источника), кажется, подразумевает, что функции-члены в этой политике должны быть статичными, что сделало бы то, что вам нужно невозможно, но, как this example показывает, Это не относится к делу.