2014-05-01 7 views
16

Coś jak Boost.Format w standardzie C++ 11? Udało mi się uniknąć użycia Boost z lepszą opcją C++ 11 na każdą inną potrzebę, jaką miałem.C++ 11 Równoważna do Boost.Format

W tym przypadku Boost.Format nie trzyma świecy w składni Pythona format(). Coś takiego byłoby jeszcze lepsze.

+0

Co z dobrym starym C/K R xxprintf()? – FoggyDay

+6

Podobają mi się ogólnie, ale nie mogę bezpośrednio zaakceptować 'string', co jest denerwujące. Wolałbym metodę, która nie wymaga od mnie wywoływania '.c_str()' na wszystkich moich ciągach. Co więcej, nie jest tak dobrze jak "format()" Pythona. –

+1

@FoggyDay: Brak bezpieczeństwa typu. W ogóle. Zero rozciągliwości. –

Odpowiedz

7

Istnieje propozycja podobna do doładowania w formacie. Jednak nie jest to ani część C++ 11, ani C++ 14, ani nic nie ma nic wspólnego z formatowaniem ciągów znaków.

Tutaj znajdziesz najnowszą propozycję. W odróżnieniu od formatu doładowania, bazuje on na szablonach variadycznych.

11

Jak słusznie wskazał nosid ani C++ C++ 11, ani 14 stanowią równowartość w celu zwiększenia Format.

Jednak fmt library który ewentualnie używa C++ 11 funkcje, takie jak o zmiennej liczbie argumentów szablonów zapewnia realizację Python podobnego format funkcji:

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

i bezpieczne alternatywy dla *printf funkcje:

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

Nota prawna: Jestem autorem tej biblioteki

0

Implementacja funkcji łańcucha znaków w stylu Pythona z szablonami wyrażeń regularnych C++ 11 i variadic.

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

przykład: cpp.sh/6nli