支持C++高级特性
下文对设备侧支持的C++高级特性(template模板和constexpr表达式)进行介绍。
template模板
template模板特性分为函数模板和类模板两种。
- 函数模板将模板特性作用在函数上,主要分为无类型模板参数、类型模板参数和变长模板参数,对于无类型和类型模板参数,又有有无默认值的区分。
- 无类型模板参数
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(); // 错误:第一个模板参数没有默认实参 *out = func<true>(); // OK, flag1 == true, flag2 == true,值为10 *out = func<false, false>(); // OK, flag1 == false, flag2 == false,值为30 }
- 类型模板参数
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); // 错误:第一个模板参数没有默认实参 *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 }
- 变长模板参数
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,参数列表分别为int,short,long, 值为70 }
- 无类型模板参数
- 类模板将模板特性作用在类上,主要分为无类型模板参数、类型模板参数和变长模板参数,针对于无类型和类型模板参数,又有有无默认值的区分。
- 无类型模板参数
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; // 错误:第一个模板参数没有默认实参 A<true> a2; // OK, flag1 == true, flag2 == true A<false, false> a3; // OK, flag1 == false,flag2 == false *out = a2.func(); // 值为10 *(out + 1) = a3.func(); // 值为30 }
- 类型模板参数
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; // 错误:第一个模板参数没有默认实参 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); }
- 变长模板参数
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参数列表为3个 *out = a.func_entry(200, 300); // 错误:参数不匹配 *out = a.func_entry(200, 300, 400); // 值为1000 *out = a.func_entry(200, 300, 400, 500); // 错误:参数不匹配 }
- 无类型模板参数
constexpr表达式
constexpr表达式是指值不会改变并且在编译过程就能得到计算结果的表达式。声明为constexpr的变量一定是一个const变量,而且必须用常量表达式初始化。
constexprint mf = 20; //20是常量表达式 constexprint limit = mf + 1; // mf + 1是常量表达式 constexprint sz = size(); //之后当size是一个constexpr函数时才是一条正确的声明语句
在if条件语句中,条件的值必须是按语境可以转换到bool类型的常量表达式,有如下表达和约束:
- 修饰表达式
template<typename T> auto inline __aicore__ get_value(T t) { if constexpr (std::is_pointer_v<T>) return *t; // 对 T = int* 推导返回类型为 int else return t; // 对 T = int 推导返回类型为 int } void inline __aicore__ f(__gm__ int* Out) { if constexpr (sizeof(int) == 3) *Out = 1; // 该代码编译期被舍去 else *Out = 2;}
- 修饰bool值
void inline __aicore__ f(__gm__ int* Out) { if constexpr (true) *Out = 1; else *Out = 2; // 该代码编译期被舍去 }
- 类中实现
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 是编译期常量,可以正常编译 res = 100; else res = 200; ConstClass t2; if constexpr (t2.c > 0) // t2 不是编译期常量,编译失败 res = 100; else res = 200; return res; }
- 舍去分支语法检查
被舍去的语句同样会经过完整的代码检查,语法错误的代码并不会因为被舍弃而被忽略。
void inline __aicore__ f() { if constexpr (false) // 该段代码不会被编译 { int i = 0; int *p = i; // 语法错误,导致编译失败 } }
父主题: 基本编程指导