当前位置: 首页 > news >正文

2308C++概念化

原文

//概念化(需要`C++20`)
struct 可画 {void(小出流 &out) const {te::call([](auto const &s, auto &out)-> decltype(s.(out)) { s.(out); }, *this, out);}
};
struct 方形 {void(小出流 &out) const { out << "方形"; }
};
template<te::概念化<可画> T>
void(T const &可画) { 可画.(cout);
}
int main() {auto 可画 = 方形{};(可画);  //打印方形
}

编译期绑定的过程

首先是利用有状态的模板元绑定鸭子类型与接口.

struct 可画 {void(小出流 &out) const {te::call([](auto const &s, auto &out)-> decltype(s.(out)) { s.(out); }, *this, out);}
};

表面是分发给自己实现的函数;但里层却被te库传递给te::callλ式的类型,绑定了可画型.
接着分析te::call的里层实现:

template <...>
constexpr auto call(const TExpr expr, const I &interface, Ts &&... args)
{...return detail::call_impl<I>(...);
}//转发template <...>
constexpr auto call_impl(...)
{void(类 映射<I, N>::元 set<型列<TExpr, Ts...> >{});return ...;
}

代码非常简单,展开实例化,绑定了映射te::call传递的λ型.
绑定是靠友元注入:

template <class, size_t>
struct 映射 final {friend auto get(映射);template <class T>struct set {friend auto get(映射) { return T{}; }};
};

实例化映射元后,get友元函数会有个声明式,此时无法确定auto返回值的类型.试实例化映射元结果的set内嵌元时,有get友元函数的定义式,此时按T绑定auto返回值的类型.

就可简单地根据能否推导出get返回值类型来决定绑定结果.以可画的示例,绑定结果如下:

映射<可画, 1>::set<型列<λ型, 小出流&>>

概念化的过程

概念化的过程.遍历所有编译期绑定结果,每个绑定都记录了鸭子类型λ类型及调用形参组成的型列.
然后测试每一个绑定的λ型,看看是否可正确实例化λ类型结果的元调用符.实现代码如下:

template <class T, class TExpr, class... Ts>
constexpr auto requires_impl(型列<TExpr, Ts...>)-> decltype(&TExpr::template operator()<T, Ts...>);
template <class I, class T, size_t... Ns>
constexpr auto requires_impl(index_sequence<Ns...>) -> 型列<decltype(requires_impl<I>(decltype(get(映射<T, Ns + 1>{})){}))...>;
}  //名字空间细节
template <class I, class T>
concept bool 概念化 = requires {detail::requires_impl<I, T>(make_index_sequence<detail::映射大小<T, I>()>{});
};

可画鸭子类型与方形实现类型的约束检查过程如下:
首先方形对象传入了方法,会实例化te::conceptfiy并检查是否满足约束:

struct 方形 {void(小出流 &out) const { out << "方形"; }
};
template<te::概念化<可画> T>
void(T const &可画) { 可画.(cout);
}(方形{});

检查约束是否满足时,会遍历可画绑定的所有接口.这里只绑定了函数,所以只会遍历一个绑定结果:

auto λ = [](auto const &s, auto &out)-> decltype(s.(out)) { s.(out); };
using λ型 = decltype(λ);
型列<λ型, 小出流&>;

此时试实例化并推导&λ型::元 符号()<小出流&>的类型,如果成功则满足约束.注意,该λ的能否成功推导关键在,λ函数体后置返回值式的推导结果:

[](auto const &s, auto &out)
//关键点:尾返回类型
-> decltype(s.(out))
//关键点:尾返回类型
{ s.(out); };

此时s的类型推到为方形 const&,如果方形类型没有实现方法,返回值推导无法,整个λ式的推导触发会SFINAE机制,导致实例化失败.
最后输出编译器错误是不满足概念化的约束,非常优雅!

http://www.lryc.cn/news/108959.html

相关文章:

  • flutter开发实战-实现自定义按钮类似UIButton效果
  • 深度优先搜索|1034, 1020, 1254
  • 都市信息供求网servlet+jsp新闻广告出售java源代码mysql
  • kubeadm init:failed to pull image registry.k8s.io/pause:3.6
  • 设计模式之简单工厂模式、工厂模式、抽象工厂模式
  • C# 控制台彩色深度打印 工具类
  • Pytorch Tensor维度变换方法
  • 微信小程序之点击文字文字自动转语音进行播放,微信小程序文字识别转语音播放
  • 主动学习、半监督学习、它们之间的区别?
  • linux快速安装Rabbitmq
  • spconv1.2.1库的编译与安装
  • java+springboot+mysql企业邮件管理系统
  • [CKA]考试之一个 Pod 封装多个容器
  • iphone备份用什么软件?好用的苹果数据备份工具推荐!
  • 一语道破 python 迭代器和生成器
  • 有哪些开源和非开源的项目管理工具?
  • 实战 01|「编写互动式界面」
  • 开源社区寻找八月创作之星!你准备好了吗~
  • appuploader不是开发者账号
  • MySQL - 10、其他命令
  • 输入框长度在XSS测试中如何绕过字符长度限制
  • JVM基础篇-直接内存
  • 【Java可执行命令】(十四)脚本执行工具jrunscript :在命令行环境下交互式执行一些简单的脚本或测试代码片段~
  • eclipse Java Editor Templates
  • vue SKU已知sku.tree算出sku.list类目值和id
  • error C4430 缺少类型说明符 - 假定为 int。注意 C++ 不支持默认 int
  • Embedding入门介绍以及为什么Embedding在大语言模型中很重要
  • 暑假刷题第20天--8/3
  • docker容器内的django启动celery任务队列
  • linux文件描述符fd