tuple
Applicability
Product |
Supported |
|---|---|
√ |
|
√ |
|
x |
|
x |
|
x |
|
x |
Function
In C++, tuple is a powerful container that allows to store multiple elements of different types. It can be used in the following scenarios:
- When a function needs to return multiple values of different types, tuple is a great option. It prevents creating a structure or class to encapsulate multiple return values, especially when you do not need to create separate types for these return values.
- When you need to store data of different types, you can use tuple to store heterogeneous elements. For example, the query result of stored data contains fields of different types.
- In function calls, if you need to pass multiple parameters of different types but do not want to create a structure for them, you can use tuple to group these parameters.
- In template metaprogramming, tuple can be used as a type list to store multiple types of information.
- When the program needs to store and transfer multiple status information in different phases, tuple can be used to store the status information in a unified manner for easy management.
- In some generic algorithms, tuple can be used to store computing results or intermediate results.
- In template metaprogramming, tuple can be used to store and expand parameter packages.
The following describes the tuple constructors:
- Default constructor: creates an empty tuple.
- Initialization list constructor: provides the element values when an object is created.
- Copy constructor: copies an existing tuple.
In addition, Ascend C provides the make_tuple function to create a tuple. This function can automatically infer the element type, making the code more concise. You can also use make_tuple to construct an element list.
Prototype
1 2 3 4 5 6 7 8 9 10 11 12 13 | template <typename Tp, typename ...Tps> class tuple<Tp, Tps...> : public tuple<Tps...> { public: __aicore__ inline tuple(); __aicore__ inline tuple(const Tp& val, const Tps& ...params); __aicore__ inline tuple(Tp&& val, Tps&& ...params); template <typename Head, typename ...Args> __aicore__ inline tuple<Tp, Tps...>& operator=(const tuple<Head, Args...>& t); } |
Parameters
Parameter |
Description |
|---|---|
Tps... |
Parameter package of the input type. The number of parameters ranges from 0 to 64. For the For the |
Restrictions
- The tuple instantiation depth is 64, that is, aggregation of data types with a maximum of 64 elements is supported.
- If the constructor is an initialization list, data in the list must be left values or right values. The number and types of elements in the initialization list must strictly match those defined by tuple.
- Variable-length data types such as arrays are not supported.
- Implicit conversion constructors are not supported.
- Currently, tuples are implemented based on inheritance. For example, the tuple<int, int> a =make_tuple(1, 2, 3) statement will trigger implicit conversion. In addition, due to the C++ object slice feature, redundant data will be discarded. Therefore, you are advised not to use the preceding statement.
Returns
None
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | AscendC::LocalTensor<T> src0Local = inQueueX.AllocTensor<T>(); AscendC::LocalTensor<T> src1Local = inQueueX2.AllocTensor<T>(); // make_tuple aggregates the tensor structure. auto testMakeTensor = AscendC::Std::make_tuple(src0Local, src1Local, src0_global, src1_global); AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(testMakeTensor)>::value); // Initialize aggregation of the list constructor. AscendC::Std::tuple<AscendC::LocalTensor<T>, AscendC::LocalTensor<T>, AscendC::GlobalTensor<T>, AscendC::GlobalTensor<T>> testTensor{src0Local, src1Local, src0_global, src1_global}; // Copy the construction mode. AscendC::Std::tuple<AscendC::LocalTensor<T>, AscendC::LocalTensor<T>, AscendC::GlobalTensor<T>, AscendC::GlobalTensor<T>> test2Tensor = testTensor; AscendC::Std::tuple<AscendC::LocalTensor<T>, AscendC::LocalTensor<T>, AscendC::GlobalTensor<T>, AscendC::GlobalTensor<T>> test3Tensor; // Operator overloading test3Tensor = test2Tensor; AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test3Tensor)>::value); // Use the get method to obtain the corresponding element. AscendC::LocalTensor<T> src0LocalTuple = AscendC::Std::get<0>(test3Tensor); AscendC::LocalTensor<T> src1LocalTuple = AscendC::Std::get<1>(test3Tensor); AscendC::GlobalTensor<T> src0_globalTuple = AscendC::Std::get<2>(test3Tensor); AscendC::GlobalTensor<T> src1_globalTuple = AscendC::Std::get<3>(test3Tensor); // Aggregate the initialization lists of multiple data types. AscendC::Std::tuple<AscendC::int4b_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, uint64_t, int64_t, half, float, \ bfloat16_t, fp8_e8m0_t, bool> test1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10.0, 11.0, 12.0, 13.0, true}; AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test1)>::value); // Use the get method to obtain elements of multiple data types. AscendC::int4b_t number_int4b_t = AscendC::Std::get<0>(test1); int8_t number_int8_t = AscendC::Std::get<1>(test1); uint8_t number_uint8_t = AscendC::Std::get<2>(test1); int16_t number_int16_t = AscendC::Std::get<3>(test1); uint16_t number_uint16_t = AscendC::Std::get<4>(test1); int32_t number_int32_t = AscendC::Std::get<5>(test1); uint32_t number_uint32_t = AscendC::Std::get<6>(test1); uint64_t number_uint64_t = AscendC::Std::get<7>(test1); int64_t number_int64_t = AscendC::Std::get<8>(test1); half number_half = AscendC::Std::get<9>(test1); float number_float = AscendC::Std::get<10>(test1); bfloat16_t number_bfloat16_t = AscendC::Std::get<11>(test1); fp8_e8m0_t number_fp8_e8m0_t = AscendC::Std::get<12>(test1); bool number_bool = AscendC::Std::get<13>(test1); // Use the get method to obtain the element reference and continue the computation. AscendC::Std::get<1>(test1)+= 1 ; AscendC::Std::get<2>(test1)+= 1 ; AscendC::Std::get<3>(test1)+= 1 ; AscendC::Std::get<4>(test1)+= 1 ; AscendC::Std::get<5>(test1)+= 1 ; AscendC::Std::get<6>(test1)+= 1 ; AscendC::Std::get<7>(test1)+= 1 ; AscendC::Std::get<8>(test1)+= 1 ; AscendC::Std::get<10>(test1) += (float)1.0 ; // Use make_tuple to initialize data types of fixed elements in the list. auto test2 = AscendC::Std::make_tuple(AscendC::int4b_t (1) ,int8_t (2) ,uint8_t (3) ,int16_t (4) ,uint16_t (5) ,int32_t (6) , \ uint32_t (7) ,uint64_t (8) ,int64_t (9) ,half (10) ,float (11) ,bfloat16_t (12) ,fp8_e8m0_t (13) , bool (true)); AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test2)>::value); // Use the get method to obtain elements of multiple data types. number_int4b_t = AscendC::Std::get<0>(test2); number_int8_t = AscendC::Std::get<1>(test2); number_uint8_t = AscendC::Std::get<2>(test2); number_int16_t = AscendC::Std::get<3>(test2); number_uint16_t = AscendC::Std::get<4>(test2); number_int32_t = AscendC::Std::get<5>(test2); number_uint32_t = AscendC::Std::get<6>(test2); number_uint64_t = AscendC::Std::get<7>(test2); number_int64_t = AscendC::Std::get<8>(test2); number_half = AscendC::Std::get<9>(test2); number_float = AscendC::Std::get<10>(test2); number_bfloat16_t = AscendC::Std::get<11>(test2); number_fp8_e8m0_t = AscendC::Std::get<12>(test2); number_bool = AscendC::Std::get<13>(test2); // Use the get method to obtain the element reference and continue the computation. AscendC::Std::get<1>(test2)+= 1 ; AscendC::Std::get<2>(test2)+= 1 ; AscendC::Std::get<3>(test2)+= 1 ; AscendC::Std::get<4>(test2)+= 1 ; AscendC::Std::get<5>(test2)+= 1 ; AscendC::Std::get<6>(test2)+= 1 ; AscendC::Std::get<7>(test2)+= 1 ; AscendC::Std::get<8>(test2)+= 1 ; AscendC::Std::get<10>(test2) += (float)1.0 ; // Aggregate the variable initialization list. AscendC::Std::tuple<AscendC::int4b_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, uint64_t, int64_t, half, float, \ bfloat16_t, fp8_e8m0_t, bool> test3 = { number_int4b_t, number_int8_t, number_uint8_t, number_int16_t, number_uint16_t, number_int32_t, number_uint32_t, \ number_uint64_t, number_int64_t, number_half, number_float, number_bfloat16_t, number_fp8_e8m0_t, number_bool, }; AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test3)>::value); uint32_t const_uint32_t = 0; float const_float = 0.0; bool const_bool = false; // Constant type const AscendC::Std::tuple<uint32_t, float, bool> test4{11, 2.2, true}; // Use the get method to obtain the constant type. const_uint32_t = AscendC::Std::get<0>(test4); const_float = AscendC::Std::get<1>(test4); const_bool = AscendC::Std::get<2>(test4); AscendC::Std::tuple_element<0,decltype(test4)>::type first = 77; AscendC::Std::tuple_element<1,decltype(test4)>::type second = 7.7; AscendC::Std::tuple_element<2,decltype(test4)>::type third = false; AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", first, second, third); AscendC::Std::tie(const_uint32_t, const_float, const_bool) = test4; AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", const_uint32_t, const_float, const_bool); // Aggregate const elements. AscendC::Std::tuple<const uint32_t, const float, const bool> test5{33, 4.4, true}; // Use the get method to obtain const elements. const_uint32_t = AscendC::Std::get<0>(test5); const_float = AscendC::Std::get<1>(test5); const_bool = AscendC::Std::get<2>(test5); const AscendC::Std::tuple<const uint32_t, const float, const bool> test6{33, 4.4, true}; const_uint32_t = AscendC::Std::get<0>(test6); const_float = AscendC::Std::get<1>(test6); const_bool = AscendC::Std::get<2>(test6); // Initialize the default construction. AscendC::Std::tuple<\ uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \ uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \ uint32_t, uint32_t, uint32_t, uint8_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,\ uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \ uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \ uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \ uint32_t, uint32_t, uint32_t, uint32_t> test7; // Initialize aggregation of default elements. auto test8 = AscendC::Std::make_tuple(\ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, \ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, \ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, \ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, \ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, \ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, \ 61, 62, 63, 64); // Overload the assignment operator. test7 = test8; AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test7)>::value); AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test8)>::value); // Use make_tuple to initialize initialization. AscendC::Std::tuple<uint32_t, float, bool> test9 = AscendC::Std::make_tuple(const_uint32_t, const_float, const_bool); const_uint32_t = AscendC::Std::get<0>(test9); const_float = AscendC::Std::get<1>(test9); const_bool = AscendC::Std::get<2>(test9); AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test9)>::value); using Element0Type = AscendC::Std::tuple_element<0, decltype(test9)>::type; Element0Type element0 = 88; using Element1Type = AscendC::Std::tuple_element<1, decltype(test9)>::type; Element1Type element1 = 8.8; using Element2Type = AscendC::Std::tuple_element<2, decltype(test9)>::type; Element2Type element2 = true; AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", element0, element1, element2); AscendC::Std::tie(const_uint32_t, const_float, const_bool) = test9; AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", const_uint32_t, const_float, const_bool); |
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Execution result: (testMakeTensor) tuple size is --> 4 (test3Tensor) tuple size is --> 4 (test1) tuple size is --> 14 (test2) tuple size is --> 14 (test3) tuple size is --> 14 (test4 tuple_element) The value of the test element is: 77, 7.700000, 0 (test4 tie) The value of the test element is: 11, 2.200000, 1 (test7) tuple size is --> 64 (test8) tuple size is --> 64 (test9) tuple size is --> 3 (test9 tuple_element) The value of the test element is: 88, 8.800000, 1 (test9 tie) The value of the test element is: 33, 4.400000, 1 |