Pav*_*nko 9 c++ templates template-meta-programming variadic-templates constexpr
假设我有一个编译时constexpr数组和一个可变参数类模板,其中包含一组与数组元素相同类型的非类型参数.
我的目标是使用数组中的值实例化类模板:
struct Container
{
int containee[3];
};
constexpr Container makeContainer();
template <int... Elements> class Foo;
Foo<makeContainer().containee[0],
makeContainer().containee[1],
makeContainer().containee[2]> foo;
Run Code Online (Sandbox Code Playgroud)
上面的代码效果很好.但是,每当我需要实例化Foo模板时,我都不得不手动索引数组.我想编译器自动为我做这件事:
Foo<Magic(makeContainer().containee)> foo;
Run Code Online (Sandbox Code Playgroud)
我在cppreference做了一些RTFM,但这没有帮助.我知道std::forward<>(),但它不能应用于模板参数列表.
改变makeContainer到一个struct与一个constexpr operator()或一个constexpr拉姆达(C++ 17) .函数指针在这里不起作用.
struct makeContainer
{
constexpr auto operator()() const
{
return Container{/* ... */};
}
};
Run Code Online (Sandbox Code Playgroud)使用std::make_index_sequence和std::index_sequence生成索引的编译时序列:
template <typename C>
constexpr auto fooFromContainer(const C& container)
{
return fooFromContainerImpl(container, std::make_index_sequence<3>{});
}
Run Code Online (Sandbox Code Playgroud)通过创建一个新的constexpr容器实例C,然后展开序列以索引常量表达式中的元素:
template <typename C, std::size_t... Is>
constexpr auto fooFromContainerImpl(const C& container, std::index_sequence<Is...>)
{
constexpr auto c = container();
return Foo<c.containee[Is]...>{};
}
Run Code Online (Sandbox Code Playgroud)只是为了好玩,这是一个C++ 20实现:
struct container { int _data[3]; };
template <int... Is>
struct foo
{
constexpr auto t() const { return std::tuple{Is...}; }
};
template <typename C>
constexpr auto foo_from_container(const C& c)
{
return []<std::size_t... Is>(const auto& c, std::index_sequence<Is...>)
{
return foo<c()._data[Is]...>{};
}(c, std::make_index_sequence<3>{});
}
int main()
{
constexpr auto r = foo_from_container([]{ return container{42, 43, 44}; });
static_assert(r.t() == std::tuple{42, 43, 44});
}
Run Code Online (Sandbox Code Playgroud)