我有一个功能foo()
,它利用类型的列表T...
和内部调用另一个名为(模板)功能do_stuff()
对于在传递一个向量的每个元素。更具体地说,我们遍历向量(长度sizeof...(T)
),并想打电话do_stuff<Ti>()
的vector[i]
,其中Ti
是i
“日式中T...
该信息在编译时可用,所以我想这是可能的,但是我们如何做到这一点呢?
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
template <typename T>
T do_stuff(int param);
template <>
int do_stuff(int param)
{
return int(100);
}
template <>
std::string do_stuff(int param)
{
return std::string("foo");
}
template <typename... T>
void foo(const std::vector<int>& p)
{
assert(p.size() == sizeof...(T));
for (int i = 0; i < p.size(); ++i)
{
// Won't compile as T is not specified:
//do_stuff(p[i]);
// How do we choose the right T, in this case Ti from T...?
}
}
int main()
{
std::vector<int> params = { 0,1,0,5 };
foo<int, std::string, std::string, int>(params);
}
您可以使用C ++ 17折叠表达式:
template <typename... T>
void foo(const std::vector<int>& p)
{
assert(p.size() == sizeof...(T));
std::size_t i{};
(do_stuff<T>(p[i++]), ...);
}
另外,您可以通过以下方式避免使用可变i
变量std::index_sequence
:
template <typename... T>
void foo(const std::vector<int>& p)
{
assert(p.size() == sizeof...(T));
[&p]<auto... Is>(std::index_sequence<Is...>)
{
(do_stuff<T>(p[Is]), ...);
}(std::index_sequence_for<T...>{});
}
我喜欢折叠解决方案,但是第二步发生了什么?那是...模板化的lambda函数吗?
@DanTony:是的,这是C ++ 20的功能。在C ++ 17中,您需要创建一个单独的模板函数,该函数采用
index_sequence
,从而产生更多样板。