类模板、函数模板和非模板函数(通常是类模板的成员)可能与约束(constraint)相关联,该约束指定对模板参数的要求(requirements),可用于选择最合适的函数重载和模板特化。约束是使用模板时需要通过模板参数满足的条件或要求。这些要求的命名集合称为概念(concept)。每个概念都是一个谓词(predicate),在编译时进行评估,并成为模板接口的一部分,用作约束。由于在编译时评估约束,因此它们可以提供更有意义的错误消息和运行时安全性。约束是表达式,概念是定义这些表达式的一种方式。
constraint:约束是一系列逻辑运算和操作数,用于指定对模板参数的要求。它们可以出现在要求表达式(requires expressions)中,也可以直接作为概念体(bodies of concepts)出现。requires关键字用于启动requires子句或requires表达式。
约束类型:
(1),conjunctions:结合了使用与(&&)运算符的多个约束。
(2).disjunctions:借助或(||)运算符组合的多个约束。
(3).atomic constraints:特定要求的个体约束。
以下为测试代码:
namespace {
template<typename T>
requires std::is_integral_v<T> || std::is_floating_point_v<T> void print_value(T value) // requires clause
{
std::cout << "value is: " << value << std::endl;
}
} // namespace
int test_constraint()
{
print_value(66);
//print_value("hello"); // error C2672: "print_value":未找到匹配的重载函数
print_value(6.6);
return 0;
}
执行结果如下图所示:
concept:概念的目的是模拟语义类别,而不是语法限制。概念是一组命名的要求。概念的定义必须出现在命名空间范围内。概念的定义具有以下形式:
template < template-parameter-list >
concept concept-name attr(optional) = constraint-expression;
(1).概念不能递归地引用自身,也不能受到约束。
(2).不允许显式实例化(explicit instantiations)、显式特化(explicit specializations)或概念的部分特化(partial specializations of concepts)(约束的原始定义的含义不能改变)。
(3).概念可以在id表达式(id-expression)中命名。如果约束表达式满足,则id表达式的值为真,否则为假。
(4).概念也可以在类型约束(type-constraint)中命名,作为type template parameter declaration, placeholder type specifier, compound requirement的一部分。
(5).在类型约束中,概念所采用的模板参数比其参数列表要求(demand)的少一个,因为上下文推断的类型被隐式地用作概念的第一个参数。
以下为测试代码:
namespace {
template<typename T>
concept Integral = std::is_integral_v<T> && sizeof(T) == 4;
template<typename T>
concept unsigned_integral = Integral<T> && !std::is_signed_v<T>;
auto func(Integral auto value)
{
std::cout << "integer value is: " << value << std::endl;
}
template<typename T>
concept Container = requires(T t) // requires expression
{
{ std::size(t) } -> std::same_as<std::size_t>;
{ std::begin(t) } -> std::same_as<typename T::iterator>;
{ std::end(t) } -> std::same_as<typename T::iterator>;
};
template<Container C>
class ContainerWrapper
{
// reference: https://www.geeksforgeeks.org/constraints-and-concepts-in-cpp-20/
public:
ContainerWrapper(C c) : container(c) {}
void print()
{
for (auto it = std::begin(container); it != std::end(container); ++it)
std::cout << *it << " ";
std::cout << "; size:" << container.size() << std::endl;
}
private:
C container;
};
} // namespace
int test_concept()
{
func(6);
//func(6.6); // error C2672: "func":未找到匹配的重载函数
short val{ 8 };
//func(val); // error C2672: "func":未找到匹配的重载函数
std::vector<int> vec1{ 1, 2, 3 };
ContainerWrapper wrapper1(vec1);
wrapper1.print();
std::vector<std::string> vec2{ "hello", "world", "!"};
ContainerWrapper wrapper2(vec2);
wrapper2.print();
return 0;
}
执行结果如下图所示: