Double / ints template function vector

I have a function that I would like to generalize. Simply put, I have std::string sone that I am processing with a parser that generates std::vector<std::string>(this is a list like in "1, 2, 3"), and the function should return std::vector<T>, with T, restricted doubleor int.

The vector must contain the converted values.

I am stuck with the last parameter std::transform, as it should switch between std::stodand std::stoi. The solution I'm looking for is template metaprogramming of magic, not if (std::is_same<T,int>::value).

Any clues?

template <class T>
auto get_vector(std::string s) -> std::vector<T>
{
    std::vector<T> v;

    auto tmp = split(s);

    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), ??);

    return v;
}
+6
source share
4 answers

, , stringstream lambda, stringstream . -

std::transform(tmp.begin(), tmp.end(), std::back_inserter(v),
    [](const std::string& elem) -> T
    {
        std::stringstream ss(elem);
        T value;
        ss >> value;
        return value;
    });
+5

std::stoi std::stod :

template <typename T>
auto parse_number(std::string const& s) -> T;

template <>
auto parse_number<int>(std::string const& s) -> int
{
    return std::stoi(s);
}

template <>
auto parse_number<double>(std::string const& s) -> double
{ 
    return std::stod(s);
}

template <class T>
auto get_vector(std::string const& s) -> std::vector<T>
{
    std::vector<T> v;
    auto tmp = split(s);
    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), &parse_number<T>);
    return v;
}
+7

Usage istream_iterator:

template <class T>
auto get_vector(std::string s) -> std::vector<T> {
    std::vector<T> v;
    std::istringstream iss(s);
    std::copy(std::istream_iterator<T>(iss), std::istream_iterator<T>(), std::back_inserter(v));
    return v;
}
+3
source

Try including logic in a try-catch block.

try {
    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), std::stoi);
} catch (const std::invalid_argument) {
    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), std::stod);
}

This has the advantage of simplicity and will tend to be fast enough.

-2
source

Source: https://habr.com/ru/post/1014687/


All Articles