在python中我们可以这样做:
def test(a, b, c):
return a+b+c
x = [1, 2, 3]
y = test(*x)
我们可以在C ++中做类似的事情吗?
答案 0 :(得分: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
变量。为此,如果L
是元组的大小(通过tuple_size),我们需要在编译时生成序列0,...,L-1
(参见例如函数range
{{3 }})。如果N...
是此序列,请使用std::get<N>(t)...
。
使用普通功能。现在test
是一个函数对象,也可以是一个lambda,但是一个普通函数应该不是模板,或者明确指定其模板参数(在tuple_call
上);否则无法推断其类型F
。
如果所有这些都集成在C ++语言中,那就太好了,但它还没有。至少有工具可以制作大致相同的东西。顺便说一句,我不知道Python中等效的运行时成本是多少。
答案 1 :(得分: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);
答案 2 :(得分: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 );
答案 3 :(得分: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中注意容器中的元素数量与预期的参数匹配,因此给定的示例不是很有用。
答案 4 :(得分: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)
但是如果你需要使用一个具有&#34; normal&#34;参数,你需要用va_args微动,参见va_arg中的例子,所以答案可能是&#34; No&#34;。