为每种类型的可变参数模板调用正确的模板专业化
Call right template specialization for each type of a variadic template
我有一个函数 foo()
,它接受一个类型列表 T...
并在内部调用另一个(模板化的)函数 do_stuff()
为传入的向量的每个元素调用。更具体地说,我们遍历向量(长度为 sizeof...(T)
),并希望为 vector[i]
调用 do_stuff<Ti>()
,其中 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);
}
下面呢?
template <typename ... T>
void foo (std::vector<int> const & p)
{
assert(p.size() == sizeof...(T));
using unused = int[];
std::size_t i{ 0u };
(void)unused { 0, ((void)do_stuff<T>(p[i++]), 0)... };
}
如果您可以使用 C++17,请参阅 Vittorio Romeo 的答案以获得更优雅和简洁的解决方案。
您可以使用 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++]), ...);
}
或者,您可以使用 std::index_sequence
:
来避免可变的 i
变量
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...>{});
}
我有一个函数 foo()
,它接受一个类型列表 T...
并在内部调用另一个(模板化的)函数 do_stuff()
为传入的向量的每个元素调用。更具体地说,我们遍历向量(长度为 sizeof...(T)
),并希望为 vector[i]
调用 do_stuff<Ti>()
,其中 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);
}
下面呢?
template <typename ... T>
void foo (std::vector<int> const & p)
{
assert(p.size() == sizeof...(T));
using unused = int[];
std::size_t i{ 0u };
(void)unused { 0, ((void)do_stuff<T>(p[i++]), 0)... };
}
如果您可以使用 C++17,请参阅 Vittorio Romeo 的答案以获得更优雅和简洁的解决方案。
您可以使用 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++]), ...);
}
或者,您可以使用 std::index_sequence
:
i
变量
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...>{});
}