Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there a syntax to avoid passing duplicated depended types?

If I want to make class TopNStorage parametrizable with comparison predicate, I have to do something like:

#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());

        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";
    }
} 

Although, this is totally fine, the int type in std::less<int> seems to be redundant in such cases and I’d like to tell the compiler to take it from typename T of the class, but I don’t know if I can parametrize the template with another template.
Is there a way to make client code look like:

TopNStorage<int,std::less> storage(3);

Motivation

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I don’t like duplication and want to avoid situations when one type could be changes without changing the other (when it comes to more complicated types and code).

Background

Based on the question Keeping top N values.

>Solution :

std::less defaults to and is specialized for void and that specialization has a comparison operator in the form of

template< class T, class U >
constexpr auto operator()( T&& lhs, U&& rhs ) const
    -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs));

allowing it to compare any two types as long as there is an underlying operator < for them.

You can use this specialization instead of specifying the type like

TopNStorage<int,std::less<>> storage(3);

which you can see working in this live example.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading