簡體   English   中英

從c ++中的字符串向量創建一個元組

[英]Create a tuple from a vector of strings in c++

我有一個字符串向量,每個字符串都是將std :: to_string應用於某些基本數據類型(例如char,int,double)的結果。 我想要一個函數來將其撤消為適當類型的元組。

我有一個簡單的函數模板來反轉std :: to_string:

template<typename T>
T from_string(std::string s)
{
}

template<>
int from_string<int>(std::string s)
{
    return std::stoi(s);
}

template<>
double from_string<double>(std::string s)
{
    return std::stod(s);
}

//... and more such specializations for the other basic types

我想要一個像這樣的功能:

template<typename... Ts>
std::tuple<Ts> undo(const std::vector<std::string>>& vec_of_str)
{
    // somehow call the appropriate specializations of from_string to the elements of vector_of_str and pack the results in a tuple. then return the tuple.     
}

該函數應該像這樣:

int main()
{
    auto ss = std::vector<std::string>>({"4", "0.5"});
    auto tuple1 = undo<int, double>(ss);
    std::tuple<int, double> tuple2(4, 0.5);

    // tuple1 and tuple2 should be identical. 
}

我認為我必須“迭代”Ts中的參數(也許正確的術語是“unpack”),調用前一個函數,from_string為每個函數,然后將from_string的每個應用程序的結果打包成一個元組。 我已經看過(並使用過)解壓縮模板參數包的示例 - 它們通常是遞歸的(但不是通常調用函數的方式),但我不知道如何做其余的事情。

一個例子:

#include <vector>
#include <string>
#include <tuple>
#include <cassert>

#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/trim.hpp>

template<class... Ts, size_t... Idxs>
std::tuple<Ts...>
parse(std::vector<std::string> const& values, std::index_sequence<Idxs...>) {
    return {boost::lexical_cast<Ts>(boost::algorithm::trim_copy(values[Idxs]))...};
}

template<class... Ts>
std::tuple<Ts...> undo(std::vector<std::string> const& values) {
    assert(sizeof...(Ts) == values.size());
    return parse<Ts...>(values, std::make_index_sequence<sizeof...(Ts)>{});
}

int main() {
    auto ss = std::vector<std::string>({"4", "0.5"});
    auto tuple1 = undo<int, double>(ss);
    std::tuple<int, double> tuple2(4, 0.5);
    std::cout << (tuple1 == tuple2) << '\n';
    assert(tuple1 == tuple2);
}

如果字符串值不包含前導和/或尾隨空格,則可以刪除對boost::algorithm::trim_copy調用。 它就在那里因為boost::lexical_cast在空格上失敗了。


如果沒有boost::lexical_cast你需要重新實現它,例如:

template<class T> T from_string(std::string const& s);
template<> int      from_string<int>(std::string const& s)    { return std::stoi(s); }
template<> double   from_string<double>(std::string const& s) { return std::stod(s); }
// And so on.

template<class... Ts, size_t... Idxs>
std::tuple<Ts...>
parse(std::vector<std::string> const& values, std::index_sequence<Idxs...>) {
    return {from_string<Ts>(values[Idxs])...};
}

對於C ++ 11 - 如果您沒有C ++ 14(Maxim的解決方案所需),或者您想要學習實現遞歸可變參數模板,則非常有用:

#include <string>
#include <vector>
#include <tuple>
#include <cassert>

template <std::size_t N, typename T>
struct Undo
{
    static void f(T& tuple, const std::vector<std::string>& vec_of_str)
    {
        Undo<N - 1, T>::f(tuple, vec_of_str);
        std::get<N - 1>(tuple) = from_string<
            typename std::tuple_element<N - 1, T>::type
        >(vec_of_str[N - 1]);
    }
};

template <typename T>
struct Undo<0, T>
{
    static void f(T&, const std::vector<std::string>&)
    {
    }
};

template <typename... Ts>
std::tuple<Ts...> undo(const std::vector<std::string>& vec_of_str)
{
    assert(vec_of_str.size() == sizeof...(Ts));
    std::tuple<Ts...> ret;
    Undo<sizeof...(Ts), std::tuple<Ts...>>::f(ret, vec_of_str);
    return ret;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM