在Python中,我们可以像这样做:
def test(a, b, c):
return a+b+c
x = [1, 2, 3]
y = test(*x)
我们能在C++中做类似的事情吗?
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中等效的运行时成本是多少。
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);
#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 );
不,没有一行代码可以将容器转换为函数所需的参数。这是因为在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]);
是的,如果你只是想将一个字面量转换为类似于向量的对象,请参见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中的示例,因此答案可能是“否”。
x
)。 - iavr