【问题标题】:Conversion of vector or array to a list of arguments in C++将向量或数组转换为 C++ 中的参数列表
【发布时间】:2017-01-04 15:40:55
【问题描述】:

我有一个第三方库,它使用同质输入参数实现重载函数,例如:

int foo(int a);
int foo(int a, int b);
int foo(int a, int b, int c);
...

现在我想编写一个包装器来接受包装在向量(或数组)中的参数:

int foo_wrapper(vector<int>& foo_args);

我该怎么做?

我查看了this answer on converting vector to tuple 的提示,但它给了我一个错误:

$ g++ -std=c++14 -o test.a test.cpp
test.cpp: In function 'int main(int, char**)':
test.cpp:23:20: error: no matching function for call to 'vectorToTuple(std::vector<int>&)'
     vectorToTuple(v);
                    ^
test.cpp:16:6: note: candidate: template<long unsigned int N, class T> auto vectorToTuple(const std::vector<T>&)
 auto vectorToTuple(const std::vector<T>& v) {
      ^~~~~~~~~~~~~
test.cpp:16:6: note:   template argument deduction/substitution failed:
test.cpp:23:20: note:   couldn't deduce template parameter 'N'
     vectorToTuple(v);
                    ^

test.cpp 存在

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

int foo(int a) {return a;};
int foo(int a, int b) {return a+b;};
int foo(int a, int b, int c) {return a+b+c;};

template <typename T, std::size_t... Indices>
auto vectorToTupleHelper(const std::vector<T>& v, std::index_sequence<Indices...>) {
  return std::make_tuple(v[Indices]...);
}

template <std::size_t N, typename T>
auto vectorToTuple(const std::vector<T>& v) {
  //assert(v.size() >= N);
  return vectorToTupleHelper(v, std::make_index_sequence<N>());
}

int main(int argc, char** argv) {
    std::vector<int> v={1,2};
    vectorToTuple(v);
}

【问题讨论】:

  • 要消除该错误,答案很明显,请提供NvectorToTuple&lt;2&gt;(v); 不知道这是否真的解决了您的问题,您在哪里调用foo

标签: c++ arguments c++14


【解决方案1】:

这个问题一般用std::vector 很难回答,但用std::arraystd::tuple 相对简单。由于您在问题中指定 std::array 会很好,因此只需进行一些调整即可使您的示例正常工作。

#include <array>
#include <iostream>
#include <tuple>
#include <utility>

int foo(int a) {return a;};
int foo(int a, int b) {return a+b;};
int foo(int a, int b, int c) {return a+b+c;};

template <std::size_t N, typename T, std::size_t... Indices>
auto call_foo_helper(const std::array<T, N>& v, std::index_sequence<Indices...>) {
  return foo(std::get<Indices>(v)...);
}

template <std::size_t N, typename T>
auto call_foo(const std::array<T, N>& v) {
  return call_foo_helper<N>(v, std::make_index_sequence<N>());
}

int main(int argc, char** argv) {
    std::array<int, 2> v={1,2};
    auto x = call_foo(v); // x = 1 + 2 = 3
    return 0;
}

编辑:

这也适用于 std::tuple,方法是将 std::array 更改为 std::tuple 并更改模板语句以匹配。

#include <iostream>
#include <tuple>
#include <utility>

int foo(int a) {return a;};
double foo(int a, double b) {return a+b;};
double foo(int a, double b, int c) {return a+b+c;};

template <typename... T, std::size_t... Indices>
auto call_foo_helper(const std::tuple<T...>& v, std::index_sequence<Indices...>) {
  return foo(std::get<Indices>(v)...);
}

template <typename... T>
auto call_foo(const std::tuple<T...>& v) {
  return call_foo_helper(v, std::make_index_sequence<sizeof...(T)>());
}

int main(int argc, char** argv) {
    auto v = std::make_tuple(1, 2.0);
    auto x = call_foo(v);
    return 0;
}

【讨论】:

  • 很好的答案,但它只有在重载函数的所有参数共享相同类型时才有效。
  • 同类型就OK
  • @FelixLauer 不确定这是否相关,因为在问题本身中,所有参数也属于同一类型。
  • @Eddge 我知道。我只是想说这不是一种完全通用的方法;)
【解决方案2】:

函数重载解析是在编译时完成的,由于std::vector&lt;&gt;的大小只有在运行时才知道,所以你必须执行代码:

int foo_wrapper(std::vector<int>& foo_args)
{
    switch (foo_args.size())
    {
        case 1: return foo(foo_args[0]);
        case 2: return foo(foo_args[0], foo_args[1]);
        case 3: return foo(foo_args[0], foo_args[1], foo_args[2]);
        default:
            throw std::range_error("Incorrect number of arguments.");
    }
}

int main(int argc, char** argv) {
    std::vector<int> v = { 1,2 };
    std::cout << foo_wrapper(v);
}

another answer 中所述,std::array&lt;&gt; 的大小在编译时是已知的,因此可以采用不同的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多