Postaron
Postaron

Reputation: 99

Is there a way to get the value_type from a template var which is function parameter?

I'm writing a virtual method, and one of its parameter a std::vector. Inside, I use std::unordered_set with the same value_type of the std::vector.

But, I may change the value_type of the std::vector, and I don't want to change each time the type inside the code. To better understand what I am saying (English is not my native language), see the code below please.

run(std::vector<Node> &data) {
    std::unordered_set<Node> var;
}

And what I expect is a thing like this :

run(std::vector<Node> &data) {
    std::unordered_set<data::value_type> var;
}

And, of course, it doesn't work. Thank you in advance.

EDIT : Thank you very much for the answers, and especially this one : https://stackoverflow.com/a/56563062/11203604

The answers with the function template, it is impossible : it is an overloaded function (virtual). As for the class template, for technical reason in my future work, I can not make it template as it could be a public class.

Thank you.

Upvotes: 3

Views: 1329

Answers (3)

Walter
Walter

Reputation: 45444

You could simply generalise your function to be a template over the container type

template<typename Container>
void run(Container const&data) const
{
    std::unordered_set<typename Container::value_type> set;
    for(auto const& x : data) {
        /* do something clever with the datum x */
    }
}

such that it will work with any container type that supports value_type.

However, traditionally the generic way in C++ is to use iterators:

template<typename Iter>
void run(Iter begin, Iter end) const
{
    using value_type = typename std::iterator_traits<Iter>::value_type;
    std::unordered_set<value_type> set;
    for(; begin != end; ++begin) {
        const value_type&x = *begin;
        /* do something clever with the datum x */
    }
}

Upvotes: 1

NathanOliver
NathanOliver

Reputation: 180660

You can use decltype to get the type of data and then apply ::value_type to that. That would give you

std::unordered_set<std::remove_reference_t<decltype(data)>::value_type> var;

As pointed out be Evg in the comments the std::remove_reference_t is needed since data is a reference and you can't apply the scope resolution operator to a reference type.

Upvotes: 5

Aconcagua
Aconcagua

Reputation: 25526

Perhaps just make a template function?

template <typename T>
void run(std::vector<T>&)
{
    std::unordered_set<T> set;
}

Upvotes: 4

Related Questions