Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Pack indexing(since C++26)

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
      Declarations
       
      Expressions
      General
      Literals
      Operators
      Conversions
       
       

      Accesses the element of apack at a specified index.

      Contents

      [edit]Syntax

      id-expression...[expression] (1)
      typedef-name...[expression] (2)
      1) Pack indexing expression
      2) Pack indexing specifier
      typedef-name - anidentifier or asimple-template-id that names a pack
      id-expression - anid-expression that names a pack
      expression - aconverted constant expressionI of typestd::size_t designated as index whereI is within the range[0sizeof...(P)) for some packP in pack indexing

      [edit]Explanation

      Pack indexing is apack expansion of the unexpanded pack followed by an ellipsis and index inside the subscript. There are two kinds of pack indexing: pack indexing expression and pack indexing specifier.

      LetP be a non-empty pack containingP0, P1, ..., Pn-1 andI be a valid index, the instantiation of the expansionP...[I] yields the pack elementPI ofP.

      Indexing a pack with non-constant expression indexI is not allowed.

      int runtime_idx(); void bar(auto...args){auto a= args...[0];constint n=1;auto b= args...[n];int m=2;auto c= args...[m];// error: 'm' is not a constant expressionauto d= args...[runtime_idx()];// error: 'runtime_idx()' is not a constant expression}

      Indexing a pack of template template parameters is not possible.

      template<template<typename...>typename...Temps>using A= Temps...[0]<>;// error: 'Temps' is a pack of template template parameters template<template<typename...>typename...Temps>using B= Temps<>...[0];// error: 'Temps<>' doesn't denote pack name// although it is a simple-template-id

      [edit]Pack indexing expression

      id-expression...[expression]

      Pack indexing expression denotes theid-expression, the expression of pack elementPI. Theid-expression shall be introduced by the declaration of:

      template<std::size_t I,typename...Ts>constexprauto element_at(Ts...args){// 'args' introduced in function parameter pack declarationreturn args...[I];} static_assert(element_at<0>(3,5,9)==3);static_assert(element_at<2>(3,5,9)==9);static_assert(element_at<3>(3,5,9)==4);// error:  out of boundsstatic_assert(element_at<0>()==1);// error: out of bounds, empty pack template<std::size_t I,typename Tup>constexprauto structured_binding_element_at(Tup tup){auto[...elems]= tup;// 'elems' introduced in structured binding pack declarationreturn elems...[I];} struct A{bool a;int b;}; static_assert(structured_binding_element_at<0>(A{true,4})==true);static_assert(structured_binding_element_at<1>(A{true,4})==4); // 'Vals' introduced in constant template parameter pack declarationtemplate<std::size_t I,std::size_t...Vals>constexprstd::size_t double_at= Vals...[I]*2;// OK template<std::size_t I,typename...Args>constexprauto foo(Args...args){return[...members= args](Args...[I] op){// 'members' introduced in lambda init-capture packreturn members...[I]+ op;};} static_assert(foo<0>(4,"Hello",true)(5)==9);static_assert(foo<1>(3,std::string("C++"))("26")=="C++26");

      Indexing pack of complex expressions other than id-expression is not allowed.

      template<std::size_t I,auto...Vals>constexprauto identity_at=(Vals)...[I];// error// use 'Vals...[I]' instead template<std::size_t I,std::size_t...Vals>constexprstd::size_t triple_at=(Vals*3)...[I];// error// use 'Vals...[I] * 3' instead template<std::size_t I,typename...Args>constexpr decltype(auto) get(Args&&...args)noexcept{returnstd::forward<Args>(args)...[I];// error// use 'std::forward<Args...[I]>(args...[I])' instead}

      Applyingdecltype to pack indexing expression is the same as applyingdecltype to id-expression.

      void f(){[](auto...args){using T0= decltype(args...[0]);// 'T0' is 'double'using T1= decltype((args...[0]));// 'T1' is 'double&'}(3.14);}

      [edit]Pack indexing specifier

      typedef-name...[expression]

      Pack indexing specifier denotes thecomputed-type-specifier, the type of pack elementPI. Thetypedef-name shall be introduced by the declaration oftype template parameter pack.

      template<typename...Ts>using last_type_t= Ts...[sizeof...(Ts)-1]; static_assert(std::is_same_v<last_type_t<>,int>);// error: out of boundsstatic_assert(std::is_same_v<last_type_t<int>,int>);static_assert(std::is_same_v<last_type_t<bool,char>,char>);static_assert(std::is_same_v<last_type_t<float,int,bool*>,bool*>);

      Pack indexing specifier can appear as:

      Pack indexing specifier can be used in function or constructor parameter list to establishnon-deduced contexts in template argument deduction.

      template<typename...>struct type_seq{}; template<typename...Ts>auto f(Ts...[0] arg, type_seq<Ts...>){return arg;} // OK: "Hello" is implicitly converted to 'std::string_view'std::same_as<std::string_view>auto a= f("Hello", type_seq<std::string_view>{}); // Error: "Ok" is not convertible to 'int'std::same_as<int>auto b= f("Ok", type_seq<int,constchar*>{});

      [edit]Notes

      Before C++26,Ts...[N] was a valid syntax for declaring function parameter pack of unnamed arrays of sizeN, where the parameter types were further adjusted to pointers. Since C++26,Ts...[1] is interpreted as a pack indexing specifier which would change the behavior below to #2. To preserve the first behavior, the function parameter pack must be named, or manually adjusted to a pack of pointer types.

      template<typename...Ts>void f(Ts...[1]); template<typename...Ts>void g(Ts...args[1]); template<typename...Ts>void h(Ts*...);// clearer but more permissive: Ts... can contain cv void or function types void foo(){    f<char,bool>(nullptr, nullptr);// behavior #1 (before C++26)://  calls void 'f<char, bool>(char*, bool*)' (aka 'f<char, bool>(char[1], bool[1])')// behavior #2 (since C++26)://  error: supposedly called 'void f<char, bool>(bool)'//  but provided with 2 arguments instead of 1     g<char,bool>(nullptr, nullptr);// calls 'g<char, bool>(char*, bool*)' (aka 'g<char, bool>(char[1], bool[1])')     h<char,bool>(nullptr, nullptr);// calls 'h<char, bool>(char*, bool*)'}
      Feature-test macroValueStdFeature
      __cpp_pack_indexing202311L(C++26)Pack indexing

      [edit]Example

      Run this code
      #include <tuple> template<std::size_t...Indices,typename Decomposable>constexprauto splice(Decomposable d){auto[...elems]= d;returnstd::make_tuple(elems...[Indices]...);} struct Point{int x;int y;int z;}; int main(){constexpr Point p{ .x=1, .y=4, .z=3};    static_assert(splice<2,1,0>(p)==std::make_tuple(3,4,1));    static_assert(splice<1,1,0,0>(p)==std::make_tuple(4,4,1,1));}
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/pack_indexing&oldid=182712"

      [8]ページ先頭

      ©2009-2025 Movatter.jp