con C++ 14 siamo autorizzati a confrontare elementi di alcuni contenitori associativi (come std :: set) con altri tipi rispetto a quelli memorizzati in un contenitore. Dovrebbe funzionare quando il comparatore ha il valore is_transparent
denotato come tipo (ad esempio, std::set::find).Come si usa il comparatore con is_transparent type?
Supponiamo di avere uno string wrapper che esegue alcuni controlli su una stringa (se il formato è formato valido e così via - non è molto importante, ma la costruzione è abbastanza pesante che vorrei evitarlo + può lanciare eccezioni) ed è memorizzato in std :: set per avere un contenitore di valori univoci. Come dovrei scrivere un comparatore per questo? Dovrebbe assomigliare a quello qui sotto? Posso sovraccaricare e usare il mio sw::operator<()
per ottenere lo stesso risultato?
class sw
{
public:
explicit sw(const std::string& s) : s_(s) { /* dragons be here */ }
const std::string& getString() const { return s_; }
bool operator<(const sw& other) const { return s_ < other.s_; }
private:
std::string s_;
};
struct Comparator
{
using is_transparent = std::true_type;
bool operator()(const sw& lhs, const std::string& rhs) const { return lhs.getString() < rhs; }
bool operator()(const std::string& lhs, const sw& rhs) const { return lhs < rhs.getString(); }
bool operator()(const sw& lhs, const sw& rhs) const { return lhs < rhs; }
};
int main()
{
std::set<sw, Comparator> swSet{ sw{"A"}, sw{"B"}, sw{"C"} };
std::cout << std::boolalpha << (swSet.find(std::string("A")) != swSet.end()) << std::endl;
}
ritengo che codice precedente dovrebbe funzionare come previsto, ma quando ho provato con g ++ 4,9 e clang ++ 3.6, sia ceduta errori di perdere conversione da string
a key_type
come se sovraccarichi stringa di Comparator::operator()
erano mai preso in considerazione. Mi sto perdendo qualcosa?
La versione di libstdC++ (la libreria standard di gcc) fornita con g ++ 4.9 non ha implementato la ricerca eterogenea. Il tuo codice [compila bene con clang e libC++] (http://coliru.stacked-crooked.com/a/97c0421099d7912d). –
@ T.C .: grazie, ha senso ed è quello che temevo ... Ho provato con clang e -stdlib = libC++ e ha funzionato come previsto. Peccato che il mio ambiente predefinito sia g ++ e libstdC++. –
È implementato in https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=219888, meno di due settimane fa. –