C++20以前,模版类型约束只能通过std::enable_if、std::enable_if_t来实现。然而,std::enable_if真的是又臭又长,而且每新定义一个都要重写一遍。直接给予模版编写者极差的使用体验。
Concepts引入之后,完美解决了std::enable_if又臭又长还得反复编写的问题。
先看下新引入的关键字:
-
concept
C++20以前,当你想定义只针对整形的模版函数,你也许会这么写:
template <typename T>
auto mod(std::enable_if_t<std::is_integral_v<T>, T> d)
{
return d % 10;
}
这样子调用
mod<int>(189);
现在你可以使用concept来约束模版类型
template <class T>
concept integral = std::is_integral_v<T>;
template <integral T>
auto mod(T d)
{
return d % 10;
}
调用方式一样
mod<int>(189);
或者这样也行
mod(189);
-
多个concept结合
concept可以把多个约束结合起
定义一个指针与整形的约束:
template <typename T>
concept pointer_integral = integral<T> || std::is_pointer_v<T>;
定义一个指针与整形的约束的函数
template <pointer_integral T>
auto sub(T d1, T d2)
{
return d1 - d2;
}
函数使用:
sub(500, 455);
int d1 = 500;
int d2 = 455;
sub(&d1, &d2);
-
requires 约束表达式
可以用代码行来约束模版类型。
template <typename T>
concept u16string_type = requires (T t)
{
t += u"";
};
requires定义的函数体里面的所有语句(可以有多行语句),在T实例化时都应该是符合C++语法规则的!
如上面的u16string_type,T类实例化类型应该支持(t += u"";)语句。
u16string_type约束函数定义:
template <u16string_type T>
auto str_add(T t)
{
return t += u"u16";
}
函数使用:
std::string s8;
//str_add(s8); //编译错误,因为不符合约束
std::u16string s16;
str_add(s16);
-
最后
concepts是很大的一块内容,限于篇幅就先写到这里。以后有时间再把concepts相关的详细用法列出来