我有带有以下签名的方法:
void DoStuff(int i);
void DoStuff(int i, k);
void DoStuff(int i, int k, int l);
我有一个方法可以从以下位置调用DoStuff方法:
void CallDoStuff(const std::vector<int>& vElements) {
// What magic is supposed to happen here to make vElements an expandable pack?
DoStuff(vElemets...);
}
有没有机会实现这一目标? 使用std :: index_sequence是否正确?如果是,请您提供一个简单的示例,将其应用于我的问题吗?
答案 0 :(得分:0)
这无法完成,模板方法调用在编译时绑定,但是std::vector
直到运行时才知道它包含多少个项目,因此无法混和这两个概念。
DoStuff(vElemets...);
在这里,编译器应根据vElements
有多少元素来选择正确的实现。您会看到这种想法的缺陷,因为std::vector
只是一个对象,在调用点可能包含任意数量的项目。
答案 1 :(得分:0)
问题在于,您无法从std::vector
-编译 时间-提取size()
值。< / p>
因此,仅当您将向量中要使用的元素数量传递给CallDoStuff()
作为编译时已知值时,您才能获得所需的内容。
您可以将其作为模板值进行传递。
使用助手功能,您可以编写如下内容
template <std::size_t ... Is>
void CallDoStuff (std::vector<int> const & vElements,
std::index_sequence<Is...> const &)
{ DoStuff(vElements[Is]...); }
template <std::size_t N>
void CallDoStuff (std::vector<int> const & vElements)
{ CallDoStuff(vElements, std::make_index_sequence<N>{}); }
电话可能是
CallDoStuff<5u>(v);
如果您可以使用std::array
而不是std::vector
,答案是不同的:您可以从类型本身中提取size()
,所以
template <std::size_t N, std::size_t ... Is>
void CallDoStuff (std::array<int, N> const & vElements,
std::index_sequence<Is...> const &)
{ DoStuff(vElements[Is]...); }
template <std::size_t N>
void CallDoStuff (std::array<int, N> const & vElements)
{ CallDoStuff(vElements, std::make_index_sequence<N>{}); }
可以调用而无需重复N
,如下所示
std::array<int, 5u> arr { 2, 3, 5, 7, 11 };
CallDoStuff(arr); // no more <5u>
尾注:请注意,std::make_index_sequence
和std::index_sequence
仅从C ++ 14开始可用。在C ++ 11中,您必须以某种方式替换它们。
答案 2 :(得分:0)
有可能,只要您提供参数数目的上限即可。
将std::index_sequence
中的Xeo's implementation用于C ++ 11:
template <unsigned... Idx>
void trampoline(const std::vector<int>& vElements, seq<Idx...>) {
return DoStuff(vElements[Idx]...);
}
template <std::size_t Arity>
void trampoline(const std::vector<int>& vElements) {
return trampoline(vElements, typename gen_seq<Arity>::seq{});
}
template <unsigned... Idx>
void CallDoStuff(const std::vector<int>& vElements, seq<Idx...>) {
using trampoline_t = void (*)(const std::vector<int>&);
constexpr trampoline_t trampolines[]{
trampoline<Idx>...
};
trampolines[vElements.size()](vElements);
}
template <std::size_t Max>
void CallDoStuff(const std::vector<int>& vElements) {
assert(vElements.size() <= Max);
return CallDoStuff(vElements, typename gen_seq<Max + 1>::seq{});
}