Se eu quiser tornar a classe TopNStorage parametrizável com predicado de comparação, tenho que fazer algo como:
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
template <typename T, typename Pred = std::greater<T>>
class TopNStorage {
std::priority_queue<T, std::vector<T>, Pred> counts;
size_t n;
public:
TopNStorage(size_t n) : n(n) { }
void add(T value) {
if (counts.size() >= n) {
if (Pred()(value, counts.top())) {
counts.pop();
counts.push(value);
}
}
else {
counts.push(value);
}
}
auto get_values() const {
std::vector<T> sorted_collocations_counts(counts.size());
std::copy(&(counts.top()), &(counts.top()) + counts.size(), sorted_collocations_counts.begin());
std::sort(sorted_collocations_counts.begin(), sorted_collocations_counts.end(),Compare());
return sorted_collocations_counts;
}
};
int main() {
TopNStorage<int,std::less<int>> storage(3);
for (int i = 1; i <= 5; ++i) {
storage.add(i);
}
for (auto value : storage.get_values()) {
std::cout << value << "\n";
}
}
Embora isso seja totalmente aceitável, o int
tipo std::less<int>
parece ser redundante nesses casos e eu gostaria de dizer ao compilador para retirá-lo typename T
da classe, mas não sei se posso parametrizar o modelo com outro modelo. Existe uma maneira de fazer o código do cliente parecer:
TopNStorage<int,std::less> storage(3);
Motivação
Não gosto de duplicação e quero evitar situações em que um tipo possa ser alterado sem alterar o outro (quando se trata de tipos e códigos mais complicados).
Fundo
Com base na pergunta Mantendo os N valores principais .
std::less
o padrão é e é especializado paravoid
e essa especialização tem um operador de comparação na forma depermitindo comparar quaisquer dois tipos, desde que haja um subjacente
operator <
para eles.Você pode usar esta especialização em vez de especificar o tipo como
que você pode ver funcionando neste exemplo ao vivo .
Desde c++ 14 você pode usar
std::less<>
e os tipos de parâmetros serão deduzidos quando o operador for invocado: https://en.cppreference.com/w/cpp/utility/funcional/lessVocê pode, portanto, apenas usar: