Advanced C++ Features
The following section introduces the advanced C++ features (templates and constexpr) supported by devices.
Templates
Templates are classified into the following two types: function template and class template.
- Function templateTemplate features are applied to functions, including non-type template parameters, type template parameters, and variadic template parameters. Both non-type template parameters and type template parameters can have default values.
- Non-type template parameters
template<bool flag1, bool flag2 = true> uint32_t inline __aicore__ func() { return flag1 ? 10 : (flag2 ? 20 : 30); } void inline __aicore__ foo(__gm__ uint32_t * out) { *out = func(); // Error: The first template parameter does not have a default argument. *out = func<true>(); // OK, flag1 == true, flag2 == true, value: 10 *out = func<false, false>(); // OK, flag1 == false, flag2 == false, value: 30 } - Type template parameters
template<typename T1, typename T2 = uint8_t> T1 inline __aicore__ func(T2 right) { return 10 + right; } void inline __aicore__ foo(__gm__ uint32_t * out) { *out = func(10); // Error: The first template parameter does not have a default argument. *out = func<uint32_t>(10); // OK, T1: uint32_t, T2: uint8_t *out = func<uint32_t, uint16_t>(10); // OK, T1: uint32_t, T2: uint16_t } - Variadic template parameters
uint32_t inline __aicore__ func() { return 10; } template<typename T, typename ...Ts> uint32_t inline __aicore__ func(T first, Ts... last) { return first + func(last...); } void inline __aicore__ foo(__gm__ uint32_t * out) { *out = func((int)10, (short)20, (long)30); // OK. The parameter list includes int, short, and long. The value is 70. }
- Non-type template parameters
- Class templateTemplate features are applied to classes, including non-type template parameters, type template parameters, and variadic template parameters. Both non-type template parameters and type template parameters can have default values.
- Non-type template parameters
template<bool flag1, bool flag2 = true> class A { public: uint8_t inline __aicore__ func() { return flag1 ? 10 : (flag2 ? 20 : 30); } }; void inline __aicore__ foo(__gm__ uint8_t * out) { A a1; // Error: The first template parameter does not have a default argument. A<true> a2; // OK, flag1 == true, flag2 == true A<false, false> a3; // OK, flag1 == false, flag2 == false *out = a2.func(); // The value is 10. *(out + 1) = a3.func(); // The value is 30. } - Type template parameters
template<typename T1, typename T2 = uint8_t> class A { public: T1 inline __aicore__ func(T2 right) { return 10 + right; } }; void inline __aicore__ foo(__gm__ uint8_t * out) { A a1; // Error: The first template parameter does not have a default argument. A<uint32_t> a2; // OK, T1: uint32_t, T2: uint8_t A<uint32_t, uint16_t> a3; // OK, T1: uint32_t, T2: uint16_t *out = a2.func(20); *(out+1) = a3.func(20); } - Variadic template parameters
template<typename ...Ts> class A { public: uint32_t inline __aicore__ func() { return 100; } template<typename T, typename ...TTs> uint32_t inline __aicore__ func(T first, TTs... last) { return first + func(last...); } uint32_t inline __aicore__ func_entry(Ts... ts) { return func(ts...); } }; void inline __aicore__ foo(__gm__ uint8_t * out) { A<int, long, short> a; // OK, func_entry has three parameters. *out = a.func_entry(200, 300); // Error: Parameter mismatch. *out = a.func_entry(200, 300, 400); // The value is 1000. *out = a.func_entry(200, 300, 400, 500); // Error: Parameter mismatch. }
- Non-type template parameters
constexpr
A constexpr expression is an expression whose value is constant and is computed at compile time. A variable declared as constexpr must be a const variable and must be initialized using a constant expression.
constexprint mf = 20; //20 is a constant expression. constexprint limit = mf + 1; // mf + 1 is a constant expression. constexprint sz = size (); // The declaration statement is correct only when size is a constexpr function.
In an if condition statement, the value of the condition must be a constant expression that can be converted to the bool type based on the context. The expressions and restrictions are as follows:
- Modifying an expression
template<typename T> auto inline __aicore__ get_value(T t) { if constexpr (std::is_pointer_v<T>) return *t; // For T = int*, the return type is int. else return t; // For T = int, the return type is int. } void inline __aicore__ f(__gm__ int* Out) { if constexpr (sizeof(int) == 3) *Out = 1; // The code is discarded during compilation. else *Out = 2;} - Modifying a bool value
void inline __aicore__ f(__gm__ int* Out) { if constexpr (true) *Out = 1; else *Out = 2; // The code is discarded during compilation. } - Implementation in a class
class ConstClass { public: int a = 2; int b = 3; int c = a * b; }; int inline __aicore__ f() { int res = 0; constexpr ConstClass t1; if constexpr (t1.c > 0) // t1 is a compilation constant. Compilation normal. res = 100; else res = 200; ConstClass t2; if constexpr (t2.c > 0) // t2 is not a compilation constant. Compilation failed. res = 100; else res = 200; return res; } - Selection syntax check
The discarded statements also go through a complete code check. The code with syntax errors is not simply ignored because it is discarded.
void inline __aicore__ f() { if constexpr (false) // This code segment will not be compiled. { int i = 0; int *p = i; // Syntax error. As a result, the compilation fails. } }
Parent topic: Basic Programming Guide