将argv和safe转换为元组

时间:2015-08-15 14:03:41

标签: c++ tuples argv

是否有可能在整数中转换任意长度的char数组并将它们安全地转换为元组?

以下是一个例子:

int main(int argc, const char* argv[]) {
  auto input = convert(argc, argv);
}

所以,如果我打电话给主要人员:

./ main 1 2

input = std::tuple<int, int>(1, 2);

./ main 2

input = std::tuple<int>(2);

我希望你明白我在寻找什么。

2 个答案:

答案 0 :(得分:4)

动态大小的元组,有一种类型?您正在寻找的是std::vector<int>

元组中元素的数量在编译时是固定的。

答案 1 :(得分:0)

我对你收到的这个问题的答案不满意,所以我找到了一个解决方案。这不应被视为表明我同意你的想法是好的: - )

将动态数据转换为静态多态功能时的问题是,您必须准备好预先构建的专业化数组 - 在运行时环境中每种可能性都有一个。这是困扰双重调度习语的同样问题。

这是一个程序的最小演示,它将argv转换为适当的tuple,然后调用模板函数(在元组的模板参数上模板化)。

我已将参数数量限制为5 +程序名称,但您可以通过在数组switch_functions中添加条目来增加此限制。

#include <iostream>
#include <tuple>
#include <vector>

using namespace std;


// this is a template of a function that does something with a tuple of strings of any size.
// it's left to the reader to figure out what to do with it.
template<class...Args>
void do_something_with_tuple(const std::tuple<Args...>& tuple)
{
    std::cout << "hello! " << sizeof...(Args) << std::endl;

}

// this is a type that manufactures a tuple of <size> strings
template<size_t size>
struct make_string_tuple
{
    using rest = typename make_string_tuple<size-1>::type;
    using mine = std::tuple<std::string>;
    using type = decltype(std::tuple_cat(std::declval<mine>(), std::declval<rest>()));

};

// this is the terminator specialisation that ends the sequence of strings in a tuple
template<>
struct make_string_tuple<0> {
    using type = std::tuple<>;
};

// this is a convenience typedef that obviates the use of the typename keyword
template<size_t size>
using make_string_tuple_t = typename make_string_tuple<size>::type;

// this is a function that initialises one element of a tuple from a corresponding position in a vector
template<size_t i, size_t n>
struct init_tuple{
    static void apply(make_string_tuple_t<n>& t, const std::vector<std::string>& x)
    {
        std::get<i>(t) = x[i];
        init_tuple<i+1, n>::apply(t, x);
    }
};

// this is the terminator specialisation for the above
template<size_t n>
struct init_tuple<n, n> {
    static void apply(make_string_tuple_t<n>& t, const std::vector<std::string>&)
    {

    }
};


// a template function that manufactures a tuple of size <size>, populates it from a vector
// which must be at least as large, and then calls the template function do_something_with_tuple
template<size_t size>
void call_it(const std::vector<std::string>& x)
{
    using tuple_type = make_string_tuple_t<size>;
    tuple_type t;
    init_tuple<0, size>::apply(t, x);
    do_something_with_tuple(t);
}

// a test program
auto main(int argc, char**argv) -> int
{
    // the type of function to call with a vector of arguments
    using switch_function = void (*)(const std::vector<std::string>&);

    // a vector of pointers to concrete versions of call_it
    static const switch_function switch_functions[] = {
        call_it<0>,
        call_it<1>,
        call_it<2>,
        call_it<3>,
        call_it<4>,
        call_it<5>,
        call_it<6>,
    };

    // convert argv into a vector of strings
    std::vector<std::string> x;
    while (argc--) {
        x.emplace_back(*argv++);
    }

    // call the appropriate version of call_it
    switch_functions[x.size()](x);


    return 0;
}