以下代码定义了函数subst_first
,它用另一个数组的内容替换int数组的第一个元素。它在gcc和clang(live demo)下工作。对于//1
,//2
和//3
个案例,其中一个生成的index_sequence
's为空。因此,//4
处的参数包之一具有零元素。这让我感到不安。我可以依靠这种行为进行标准符合吗?
template<size_t n, size_t ... S1, size_t ... S2>
constexpr
std::array<int,3>
subst_first_impl( std::array<int,n> const &v1,
std::array<int,3> const &v2,
size_t min_n,
std::index_sequence<S1...>,
std::index_sequence<S2...> )
{ return std::array<int,3>{{ v1[S1]..., v2[min_n+S2]... }}; } // 4
template<size_t n>
constexpr
std::array<int,3>
subst_first( std::array<int,n> const &v1,
std::array<int,3> const &v2 )
{ auto const min_n= std::min( size_t(3), n );
return subst_first_impl( v1, v2, min_n,
std::make_index_sequence< min_n >(),
std::make_index_sequence< size_t(3) - min_n >() );
}
int main(){
constexpr std::array<int,3> a1{{1,2,3}};
constexpr std::array<int,2> b1{{4,5}};
constexpr std::array<int,3> b2{{6,7,8}};
constexpr std::array<int,4> b3{{9,10,11,12}};
constexpr std::array<int,0> b4{};
constexpr auto b1a1= subst_first( b1, a1 );
// ==> 4, 5, 3
constexpr auto b2a1= subst_first( b2, a1 ); // 1
// ==> 6, 7, 8
constexpr auto b3a1= subst_first( b3, a1 ); // 2
// ==> 9, 10, 11
constexpr auto b4a1= subst_first( b4, a1 ); // 3
// ==> 1, 2, 3
}
注意:我不是在寻找替换数组元素的解决方案。我对index_sequence
和参数包的行为感兴趣。
答案 0 :(得分:2)
是的,绝对的。引用标准[temp.variadic]:
- 包装扩展由图案和省略号组成 实例化生成零或更多实例化 列表中的模式。模式的形式取决于上下文 发生了扩张。
醇>
因此,该标准适用于大小为零的包的扩展。
答案 1 :(得分:2)
首先,std::make_index_sequence<0>
完全有效(§20.5.3[intseq.make]):
[注意:make_integer_-sequence&lt; int,0&gt;表示类型integer_sequence&lt; int&gt; - 尾注]
所以在你的情况下,你得到一个std::index_sequence<size_t>
。
根据§14.5.3/ 7 [temp.variadic],长度为0的包扩展的实例化是完全有效的:
既不是
sizeof...
表达式也不是fold-expression的包扩展的实例化产生列表E1,E2,...,EN,其中N是包扩展参数中的元素数。 [...]所有E i 都成为封闭列表中的元素。 [...]当 N为零时,扩展的实例化会生成一个空列表。这样的实例化不会改变封闭结构的句法解释,即使在完全省略列表的情况下也会形成错误或导致语法模糊不清。