我可以依赖空参数包来正确扩展吗?

时间:2016-07-01 13:04:20

标签: c++ c++14 variadic-templates

以下代码定义了函数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和参数包的行为感兴趣。

2 个答案:

答案 0 :(得分:2)

是的,绝对的。引用标准[temp.variadic]:

  
      
  1. 包装扩展由图案和省略号组成   实例化生成零或更多实例化   列表中的模式。模式的形式取决于上下文   发生了扩张。
  2.   

因此,该标准适用于大小为零的包的扩展。

答案 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为零时,扩展的实例化会生成一个空列表。这样的实例化不会改变封闭结构的句法解释,即使在完全省略列表的情况下也会形成错误或导致语法模糊不清。