假设我有一个静态存储持续时间的 constexpr 数组(已知边界):
constexpr T input[] = /* ... */;
我有一个需要包的输出类模板:
template<T...> struct output_template;
我想实例化
output_template
,例如:
using output = output_template<input[0], input[1], ..., input[n-1]>;
执行此操作的一种方法是:
template<size_t n, const T (&a)[n]>
struct make_output_template
{
template<size_t... i> static constexpr
output_template<a[i]...> f(std::index_sequence<i...>)
{ return {}; };
using type = decltype(f(std::make_index_sequence<n>()));
};
using output = make_output_template<std::extent_v<decltype(input)>, input>::type;
我缺少更干净或更简单的解决方案吗?
也许你认为这样更干净:
template< const T* a, typename >
struct make_output_template;
template< const T* a, std::size_t... i >
struct make_output_template< a, std::index_sequence< i... > >
{
using type = output_template< a[ i ]... >;
};
与
using output = make_output_template<
input,
std::make_index_sequence< std::extent_v< decltype( input ) > >
>::type;
C++ 17 更新: 使用自动模板参数,我们可以使 OP 的解决方案和 Daniel Frey 的 答案更好用一些。以OP为例:
template<auto& input>
using output = make_output_template<std::extent_v<std::remove_reference_t<decltype(input)>>, input>::type;
可以直接使用,例如:
outupt<input> foo;
。
请务必使用
auto&
正确捕获数组。使用裸的 auto
它将衰减为常规指针(参见例如 https://stackoverflow.com/a/6443267),std::extent_v
将为零,但代码仍然可以编译,并且如果您期望可变参数将 output_template
打包为与 input
数组大小相同,你就有了一个全新的 bug。