将向量的内容作为参数传递给函数的C++方法

4
在Python中,我们可以像这样做:
def test(a, b, c):
    return a+b+c

x = [1, 2, 3]
y = test(*x)

我们能在C++中做类似的事情吗?

5个回答

2
到目前为止提出的解决方案都是基于对函数参数进行运行时迭代,这会产生一些成本。它们还假设参数类型相同。如果在编译时已知参数数量(通常是这样),则可以采用不同的解决方案,如下所示:
template <typename F, typename T>
auto tuple_call3(F&& f, const T& t)
-> decltype(std::forward<F>(f)(std::get<0>(t), std::get<1>(t), std::get<2>(t)))
   { return std::forward<F>(f)(std::get<0>(t), std::get<1>(t), std::get<2>(t)); }

struct test
{
   template <typename A, typename B, typename C>
   auto operator()(const A& a, const B& b, const C& c)
   -> decltype(a + b + c)
      { return a + b + c; }
};

int main()
{
    auto x = std::make_tuple(1, 2, 3);
    auto y = tuple_call3(test(), x);
    cout << y << endl;
}

这个技术没有运行时成本,并且可以与异构参数类型一起使用。我现在没有时间进一步开发它,但是要使它完全通用,我们需要:

  • 在所有地方都使用万能引用(如 F&&)和转发(如 std::forward<F>(f)),当然包括函数参数。

  • 使tuple_call可变参数化。为此,如果通过tuple_size得到元组的大小为L,则需要在编译时生成序列0,...,L-1(参见 这里 的函数range)。如果N... 是这个序列,则使用std::get<N>(t)...

  • 使其适用于普通函数。现在test是一个函数对象,也可以是一个lambda表达式,但是普通函数应该不是一个模板,或者其模板参数应该明确指定(在tuple_call上);否则无法推断出其类型F

如果所有这些都能集成到C++语言中就太好了,但它现在还没有(至少)这个功能。顺便说一下,我不知道在Python中等效的运行时成本是多少。


1
至少,我认为以下代码接近于你的Python代码。
int test(const std::vector<int>& v)
{
    return std::accumulate(v.begin(), v.end(), 0);
}

std::vector<int> x = { 1, 2, 3 };
int y = test(x); 

1
是的,你可以。例如:
#include <numeric>
#include <initializer_list>

int test( std::initializer_list<int> l )
{
    return std::accumulate( l.begin(), l.end(), 0 );
}

int y = test( { 1, 2, 3 } );

或者

int test( const int a[] )
{
    return a[0] + a[1] + a[2];
}

int a[] = { 1, 2, 3 };
int y = test( a );

或者

#include <vector>
#include <numeric>
int test( const std::vector<int> &v )
{
    return std::accumulate( v.begin(), v.end(), 0 );
    // or return v[0] + v[1] + v[2];
}

std::vector<int> v = { 1, 2, 3 };
int y = test( v );

0

不,没有一行代码可以将容器转换为函数所需的参数。这是因为在C++中,函数调用在编译时处理,而容器的内容在运行时才能确定。

因此,我最接近的例子是

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

std::vector<int> x = { 1, 2, 3 };
int y = test(x[0], x[1], x[2]);

需要注意的是,在Python中,您必须确保容器中的元素数量与期望的参数相匹配,因此给出的示例并不是非常可用的。

请检查我的编译时替代方案(取决于我们对“容器”的定义以及如何定义x)。 - iavr
@iavr:我看到了你的回答,有一些相似之处,但我的回答是关于将容器转换为常规函数的参数。但基于不同的答案,这个问题留下了解释的余地。 - stefaanv

0

是的,如果你只是想将一个字面量转换为类似于向量的对象,请参见std::initializer_list(C++11)

template <typename T>
void test(std::initializer_list<T> aList) {
    //do stuff with aList, for example std::accumulate,
    //or make a vector with it: std::vector<T> v(aList);
}

auto x = {10, 11, 12};
test(x)

但如果您需要使用具有“正常”参数的函数,则需要使用va_args,详见va_arg中的示例,因此答案可能是“否”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接