C++20中的约束与概念

      类模板、函数模板和非模板函数(通常是类模板的成员)可能与约束(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;
}

      执行结果如下图所示:

      GitHubhttp://github.com/fengbingchun/Messy_Test

  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值