mardi 29 novembre 2016

In C++11 is there anyway to get the general template class from a template class with specified template arguments?

(e.g. get std::list from std::list<some_value_type>)

Consider the following code:

#include <list>
#include <string>

std::string combine(int val, std::string str)
{
    return std::to_string(val) + str;
}

template <class T, class U>
auto foo(const T &container, const U &val)
    -> std::list<U>
{
    using RetType = std::list<U>;
    RetType result;

    for(auto item : container) {
        result.push_back(combine(item, val));
    }

    return result;
}

int main()
{
    std::list<int> numbers = {1, 2, 3, 4, 5};
    std::list<std::string> result = foo(numbers, std::string(" potato"));
    return 0;
}

This compiles, but I want it to work differently. I'd like foo to return the same kind of container as was passed into its first argument, but with its value type changed to that of the second argument, i.e. type U.

So if foo is passed in std::list<int> as its first argument and std::string as its second argument, it returns std::list<std::string>. Alternatively, if foo is passed in std::vector<int> as its first argument and std::string as its second argument, it returns std:: vector<std::string>. And so on.

Basically I want to replace both instances of std::list<U> with something that accomplishes the above, possibly using the facilities of <type_traits>.

Is there anyway to do this in C++11? The only solution I've found is to create overloaded versions of foo for every container type I want to use, but I'd much prefer if there was a general way to do it that covered all container types.

Aucun commentaire:

Enregistrer un commentaire