我有一个第三方库,它使用同类输入参数实现重载函数,例如:
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);
}
答案 0 :(得分:5)
这个问题很难通过std::vector
来回答,但对于std::array
或std::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;
}
答案 1 :(得分:2)
函数重载解析在编译时完成,由于std::vector<>
的大小仅在运行时已知,因此您必须执行代码:
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<>
的大小在编译时是已知的,这允许使用不同的解决方案。