假设我有一个编译时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;
以上代码效果很好。但是,每当我需要实例化Foo
模板时,我都不得不手动索引数组。我想编译器自动为我做这件事:
Foo<Magic(makeContainer().containee)> foo;
我在cppreference做了一些RTFM,但这没有帮助。我知道std::forward<>()
,但它不能应用于模板参数列表。
答案 0 :(得分:7)
使用makeContainer
或struct
lambda (C ++ 17)将constexpr operator()
更改为constexpr
。函数指针在这里不起作用。
struct makeContainer
{
constexpr auto operator()() const
{
return Container{/* ... */};
}
};
使用std::make_index_sequence
和std::index_sequence
生成索引的编译时序列:
template <typename C>
constexpr auto fooFromContainer(const C& container)
{
return fooFromContainerImpl(container, std::make_index_sequence<3>{});
}
通过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]...>{};
}
complete example on wandbox.org
只是为了好玩,这是一个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});
}