2010-04-27 13 views

risposta

2

Dopo aver osservato questo per più di un'ora, mi sento abbastanza sicuro dicendo: "non può essere fatto capitano". Anche nel codice boost, eseguono l'iterazione sul vettore private named_marks_ durante la ricerca. Semplicemente non è configurato per permetterlo. Direi che la migliore scommessa sarebbe quella di iterare su quelli che pensi dovrebbero essere lì e prendere l'eccezione per quelli che non sono stati trovati.

const_reference at_(char_type const *name) const 
{ 
    for(std::size_t i = 0; i < this->named_marks_.size(); ++i) 
    { 
     if(this->named_marks_[i].name_ == name) 
     { 
      return this->sub_matches_[ this->named_marks_[i].mark_nbr_ ]; 
     } 
    } 
    BOOST_THROW_EXCEPTION(
     regex_error(regex_constants::error_badmark, "invalid named back-reference") 
    ); 
    // Should never execute, but if it does, this returns 
    // a "null" sub_match. 
    return this->sub_matches_[this->sub_matches_.size()]; 
} 
3

Con Boost 1.54.0 questo è ancora più difficile perché i nomi delle acquisizioni non vengono nemmeno memorizzati nei risultati. Invece, Boost semplicemente annulla i nomi delle acquisizioni e memorizza l'hash (uno int) ei puntatori associati alla stringa originale.

Ho scritto una piccola classe derivata da boost::smatch che salva i nomi di acquisizione e fornisce un iteratore per loro.

class namesaving_smatch : public smatch 
{ 
public: 
    namesaving_smatch(const regex& pattern) 
    { 
     std::string pattern_str = pattern.str(); 
     regex capture_pattern("\\?P?<(\\w+)>"); 
     auto words_begin = sregex_iterator(pattern_str.begin(), pattern_str.end(), capture_pattern); 
     auto words_end = sregex_iterator(); 

     for (sregex_iterator i = words_begin; i != words_end; i++) 
     { 
      std::string name = (*i)[1].str(); 
      m_names.push_back(name); 
     } 
    } 

    ~namesaving_smatch() { } 

    std::vector<std::string>::const_iterator names_begin() const 
    { 
     return m_names.begin(); 
    } 

    std::vector<std::string>::const_iterator names_end() const 
    { 
     return m_names.end(); 
    } 

private: 
    std::vector<std::string> m_names; 
}; 

La classe accetta l'espressione regolare che contiene i gruppi di cattura con nome nel suo costruttore. Usa la classe in questo modo:

namesaving_smatch results(re); 
if (regex_search(input, results, re)) 
    for (auto it = results.names_begin(); it != results.names_end(); ++it) 
     cout << *it << ": " << results[*it].str();