(C++) Cpp20 概念和约束

前言

模板技术是c++中的一项非常重要的技术。

而SFINAE更是在整个体系中起着举足轻重的分量。

而对于支撑这概念的各种技巧也是在不断发展。

Cpp20前

在cpp20前通常是用 std::enable_if<>来实现。

比如要判断一个类型是否是const限定,可以像下面这么写。

cpp11

#include <type_traits>

template <typename T,
          typename C = typename std::enable_if<std::is_const<T>::value>::type>
void fun() {
}

int main() {
    // ok
    fun<const int>();

    // error
    // fun<int>();

    return 0;
}

cpp14~cpp17

在cpp14 中对enable_if 定义了辅助变量模板 enable_if_t

在cpp17 中对is_const 定义了辅助变量模板 is_const_v

#include <type_traits>

template <typename T,
          typename C = typename std::enable_if_t<std::is_const_v<T>>>
void fun() {
}

int main() {
    // ok
    fun<const int>();

    // error
    // fun<int>();

    return 0;
}

Cpp20

下面两种方式均等效。

concept

在cpp20中可以直接用concept 关键字定义一个约束

并在模板中直接使用整个约束

#include <iostream>
#include <concepts>
#include <type_traits>

template <class T>
concept IsConst = std::is_const_v<T>;

template <IsConst T>
void fun(T t) {
    std::cout << t << std::endl;
}

int main() {
    // ok
    fun<const int>(1);

    // error
    // fun<int>();

    return 0;
}

requires

#include <iostream>
#include <concepts>
#include <type_traits>

template <class T>
requires std::is_const_v<T>
void fun(T t) {
    std::cout << t << std::endl;
}

int main() {
    // ok
    fun<const int>(1);

    // error
    // fun<int>();

    return 0;
}

概念与约束的规则

requires 子句的使用规则

  • 要求是为bool的纯右值常量表达式
  • 是初等表达式 或者 带括号的表达式
  • 可以使用&&或者||连接表达式 (遵循短路原则)

顺序规则

下方例子为《现代C++语言核心特性解析》中p399,400的一个例子

#include <concepts>
#include <type_traits>

template <class C>
concept ConstType = std::is_const_v<C>;

template <class C>
concept IntegralType = std::is_integral_v<C>;

template <ConstType T>
    requires std::is_pointer_v<T>
void foo(IntegralType auto)
    requires std::is_same_v<T, char* const>
{
}

int main() {
    // 满足所有条件
    foo<char *const>(1);
    return 0;
}

顺序分别为出现顺序:

  1. template <ConstType T>
  2. requires std::is_pointer_v<T>
  3. IntegralType auto
  4. requires std::is_same_v<T, char* const>

requires 表达式

是的将 concept 和 requires 结合还能写更像函数。

注意在scope中可以写多行,是且的条件。

#include <concepts>
#include <type_traits>

template <class T>
concept check = requires {
    // 满足有该表达式的才允许通过
    // 只会在编译阶段判断合法性,而不会实际运行
    T{}.resize(1);
};

template <class C>
concept IntegralType = std::is_integral_v<C>;

template <check T>
void foo(T) {
}

#include <queue>
#include <string>
#include <vector>
int main() {
    // ok
    foo<std::vector<int>>({});
    foo(std::string{});

    // error
    // foo(std::queue<int>{});

    return 0;
}



END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值