2014-05-01 12 views
16

Qualcosa come Boost.Format nello standard C++ 11? Sono stato in grado di evitare l'uso di Boost con una migliore opzione C++ 11 per ogni altra esigenza che ho avuto.C++ 11 Equivalente a Boost.Format

In questo caso, Boost.Format non contiene una candela per la sintassi di Python format(). Qualcosa del genere sarebbe ancora meglio.

+0

Cosa c'è di sbagliato con il buon vecchio C/K & R xxprintf()? – FoggyDay

+6

Mi piace in generale ma non può accettare direttamente 'string', che è fastidioso. Preferirei un metodo che non mi imponga di chiamare '.c_str()' su tutte le mie stringhe. Inoltre, non è neanche lontanamente bello come il 'format()' di Python. –

+1

@ FoggyDay: nessuna sicurezza del tipo. Affatto. Zero estensibilità. –

risposta

7

C'è una proposta per qualcosa di simile al formato boost . Tuttavia, non fa parte né di C++ 11 né di C++ 14, né è stato aggiunto nulla relativo alla formattazione delle stringhe.

Qui puoi trovare l'ultima proposta. A differenza del formato boost , è basato su modelli variadici.

11

Come correttamente rilevato dal nosid né C++ 11 né C++ 14 fornire un equivalente Boost definizione.

Tuttavia, la fmt library che utilizza opzionalmente C++ 11 funzioni come modelli variadic fornisce un'implementazione della funzione Python-like format:

std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy"); 

alternative sicure ed *printf funzioni:

fmt::printf("The answer is %d\n", 42); 

Disclaimer: Sono l'autore di questa libreria

0

Implementazione della funzione di stringa di formato simile a Python con modelli regex e variadic di C++ 11.

/** 
    Helper code to unpack variadic arguments 
*/ 
namespace internal 
{ 
    template<typename T> 
    void unpack(std::vector<std::string> &vbuf, T t) 
    { 
     std::stringstream buf; 
     buf << t; 
     vbuf.push_back(buf.str()); 
    } 
    template<typename T, typename ...Args> 
    void unpack(std::vector<std::string> &vbuf, T t, Args &&... args) 
    { 
     std::stringstream buf; 
     buf << t; 
     vbuf.push_back(buf.str()); 
     unpack(vbuf, std::forward<Args>(args)...); 
    } 
} 

/** 
    Python-like string formatting 
*/ 
template<typename ... Args> 
std::string format(const std::string& fmt, Args ... args) 
{ 
    std::vector<std::string> vbuf; // store arguments as strings 
    std::string in(fmt), out; // unformatted and formatted strings 
    std::regex re_arg("\\{\\b\\d+\\b\\}"); // search for {0}, {1}, ... 
    std::regex re_idx("\\b\\d+\\b");  // search for 0, 1, ... 
    std::smatch m_arg, m_idx;    // store matches 
    size_t idx = 0;       // index of argument inside {...} 

    // Unpack arguments and store them in vbuf 
    internal::unpack(vbuf, std::forward<Args>(args)...); 

    // Replace all {x} with vbuf[x] 
    while (std::regex_search(in, m_arg, re_arg)) { 
     out += m_arg.prefix(); 
     if (std::regex_search(m_arg[0].str(), m_idx, re_idx)) { 
      idx = std::stoi(m_idx[0].str()); 
     } 
     if(idx < vbuf.size()) { 
      out += std::regex_replace(m_arg[0].str(), re_arg, vbuf[idx]); 
     } 
     in = m_arg.suffix(); 
    } 
    out += in; 
    return out; 
} 

Esempio: cpp.sh/6nli