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

C++ 模板参数推导问题小记(模板类的模板构造函数)

本篇主要是为了记录在编写一个模板类的模板构造函数中遇到的初始化问题,以及针对这个问题展开的相关知识整理,文章就以引发这个问题的代码为标题了。

问题代码

在编写一个代表空间点的模板类 point 时,我打算为它添加一个模板构造函数:

代码

template<typename T, std::size_t N>
struct point
{using value_type = scalar<T>;value_type _v[N];
point() : _v{ value_type{} } {}
template<typename U>explicit point(const U (&arr)[N]){if constexpr(std::is_same_v<value_type, U>)memcpy(_v, arr, n * sizeof(value_type));else{for(std::size_t i = 0; i != N; ++i)_v[i] = static_cast<value_type>(arr[i]);//抑制“”}} };
point<int, 3> pi3({ 0, 1, 2 });

代码中的 scalar 是 这篇 笔记中提到用于类型限制的别名模板,用以排除非数值类型的模板实例化。

template<typename U> point(const U (&arr)[N]) 这个构造函数的意图是 point 只接受长度为 N 的数组进行初始化。

一切看起来没什么问题,但是当我写下这样的初始化代码时,发现代码仍然能够正常通过编译:

代码

point<int, 3> pi3({ 0, 1 });
{{the-copyright}}*本*文*由*博*客*园* @saltymilk *原*创*{{/the-copyright}}

为什么料想之中的长度限制并没有起作用?

问题分析

分析 point<int, 3> pi3({ 0, 1 }); 这句代码,编译器是如何处理它的:

1. point<int, 3> pi3 指定了 pi3 这个实例的 TintN3

2. pi3({ 0, 1 }) 是一个单参数构造语句,尝试匹配接受单个参数的构造函数,匹配到接受数组引用的自定义构造函数 template<typename U> point<int, 3>::point(const U (&arr)[3])

3. 根据调用参数 { 0, 1 },即 [int, int] 推导 Uint,构造函数实例化为 point<int, 3>::point<int>(const int (&arr)[3]);

4. 使用 { 0, 1 } 对一个临时的 int [3] 进行列表初始化,初始化结果为 { 0, 1, 0 },随后传入构造函数。

point 类的模板参数 N 在类的实例化时被指定为 3,在成员模板构造函数实例化期间它是已知的,函数参数推导过程对它没有任何影响,这句代码能够通过编译的根本原因是长度为 3 的数组能够被只有 2 个元素的初始化列表初始化。

而我由于对初始化细节了解不全面,加之模板代码对问题分析有一定的干扰,让我一时没有抓住本质,写出了这段一厢情愿的代码。

问题解决

解决方法很简单,把数组的维度也作为模板参数参与推导,然后对它进行约束就能实现这个目的了:

代码

template<typename U, std::size_t M, typename = std::enable_if_t<M == N>>
explicit point(const U (&arr)[M])
{//...
};
int iarr[] = { 0, 1, 2 }; point<int, 3> pi30(iarr);//OK point<int, 3> pi31({ 0, 1, 2 });//OK point<int, 3> pi3({ 0, 1 });//无法通过编译 {{the-copyright}}*本*文*由*博*客*园* @saltymilk *原*创*{{/the-copyright}}

现在数组的维度 M 需要从构造函数的参数推导出来,如果 MN 不相等,构造函数实例化失败。

问题到此就可以结束了,但是不妨来分析一下 ({ ... }) 这种初始化写法。

C++ 的初始化

首先复习一下基础知识,不考虑拷贝构造的情况下,C++ 的初始化有两种:

1. (...),即直接初始化

这种调用适用于类类型,直接要求调用类的某个构造函数。所有用户自定义和编译器合成版本的构造函数都会被加入候选列表,随后根据重载函数匹配规则选出匹配度最高的一个进行调用,无匹配项或多个项都具有最佳匹配度时匹配失败。

这种初始化语法有个缺陷 —— 可能会被解析为函数声明,在这些情况下,解析的结果往往很反直觉,所以被称为 最令人烦恼的解析。

2. = { ... } & { ... },即 列表初始化

在 C++11 标准之前,列表初始化只能用来对 聚合类型 进行初始化。上文中使用 { 0, 1 } 将一个临时的 int [3] 初始化为 { 0, 1, 0 } 就属于聚合类型的列表初始化。更加详细的规则不是本文的重点关注对象,感兴趣的话可以到 这里 阅读。

值得一提的是,MSVC(测试版本为 _MSC_VER=1943)支持使用 (...) 对聚合类型进行列表初始化,但这并不被 C++ 标准采纳,属于 MSVC 方言,不具备可移植性,使用时须当心。

C++11 引入了统一初始化语法,使得任何类型都能够使用列表初始化语法进行初始化,同时新增了 std::initializer_list 来支持统一的列表初始化语法。

列表初始化语法杜绝了将初始化语句解析为函数声明语句的可能,并且阻止了 窄化转换,使初始化更加简洁安全。

在使用列表初始化器初始化对象时,接受 std::initializer_list 的构造函数具有无与伦比的重载匹配优先级,即使无法正确构造一个 std::initializer_list 且其他函数能够精确匹配参数时也可能直接屏蔽其他构造函数,直接报错而不尝试其他重载版本(Scott Meyers, Effective Modern C++, Item 7)。所以除非你非常确定自己的类需要一个接受 std::initializer_list 的构造函数,并且你能够正确处理它与其他构造函数的关系,不要轻易定义这个构造函数。

({ ... }) 是如何解析的

有了前面的铺垫,这个初始化语句就很好理解了。外层的 () 指定要调用某个函数,该函数能够匹配只有一个参数的调用形式,内层的 { ... } 作为一个初始化列表对这个参数进行初始化。

列表初始化 指定的情形是直接包含这种初始化形式的,并且解释得非常详细:

copy-list-initialization

其实我们平时也经常在函数调用时使用这种语法:

代码

void foo(int i, const std::vector &vec);//函数签名
foo(0, { 0, 1, 2 });//调用

当它被用于类的初始化时,编译器自动匹配构造函数调用,匹配规则与普通函数是一样的。

再探 point 的初始化

前面对 point 构造的分析只是简化版,让我们再次详细分析这一句代码的解析过程:

point pi3({ 0, 1 }); 这个调用中的 ({ 0, 1 }) 会匹配所有接受单个参数、名为 point 的函数。查看一下候选的函数,编译器发现有三个:用户定义的接受数组引用的构造函数,自动合成的拷贝构造函数,以及自动合成的移动构造函数。分别分析它们的匹配情况:

匹配接受数组引用的构造函数 point<int, 3>::point<int>(const int (&arr)[3]),此构造函数的形参是 const int (&)[3]。根据聚合类型的列表初始化规则,指定长度的数组可被元素数量小于或等于其长度的初始化列表初始化。此处创建一个临时数组 int [3] 并且被初始化为 { 0, 1, 0 },绑定到数组引用形参上,函数匹配成功。

匹配拷贝构造函数 point<int, 3>::point(const point<int, 3> &),其形参是 const point<int, 3> &。这里需要创建一个临时的 point<int, 3>,相当于 point<int, 3> temp{ 0, 1 };。显然,point<int, 3> 既不是聚合类型,也没有接受 (int, int) 的构造函数,更没有接受 std::initializer_list 的构造函数。这样一个临时的变量无法被创建出来,所以拷贝构造函数匹配失败。

移动构造函数的情形与拷贝构造函数相同,无法匹配。

最终,自定义的那个接受数组引用的构造函数被选中用来初始化这个 point<int, 3> 实例。

语义检查与优化

point 类的定义使得 ({ 0, 1 }) 无法匹配到拷贝构造或移动构造函数,但是如果我们定义下面这样一个能被两个 int 参数构造的类:

代码

struct S
{S(int, int) {}
//S(const S &) = delete;//如果删除拷贝构造函数,按照语言规则,移动构造函数也不会自动合成 };
S s({ 0, 1 });//若拷贝构造函数被删除,无法通过编译 S s1 = S{ 0, 1 };//若拷贝构造函数被删除,可以通过编译(C++17之后) {{the-copyright}}*本*文*由*博*客*园* @saltymilk *原*创*{{/the-copyright}}

按照前面讲述的,s 的构造会调用用户定义的构造函数和编译器合成的移动构造函数,即先构造一个临时的 S 对象,再用这个临时对象调用移动构造函数。这样的构造过程显然是冗余的,中间这个临时对象被创建出来后立即用于后续的构造,没有任何可能会被修改,所以它的构造完全可以直接发生在最终目标位置。

大多数编译器确实会优化掉这个中间过程,但是如果我们像代码注释中那样让 S 的移动构造函数和拷贝构造函数不可用,编译器会提示 s 的构造中引用了被删除的函数。那些确实会执行这项优化的编译器,为什么必须检查一定不会被引用的函数的可用性呢?

这是因为编译器执行代码优化的基础是代码必须按照语言标准进行编写,而确保代码符合语言标准的工作是由语义检查环节完成的。也就是说,代码优化必须在语义检查通过后才能执行(实际的编译中这两个环节之间还会有其他操作),那么为什么语义同样是调用移动构造函数的 s1 构造语句不会报错呢?

我们知道,从 C++17 开始,有一些 拷贝省略 是强制施行的,即原来这些被视作优化的拷贝省略形式被纳入标准行为。其中就包括上述代码中 s1 的构造情形:

mandatory-copy-elision

既然 s1 构造中省略拷贝步骤已是标准行为,编译器的语义检测就只需要检查对应的构造函数可用性就行了(前提是设置编译器的语言标准大于 C++17)。

s 的构造语句形式不在强制拷贝省略的情形之列,所以如果拷贝构造函数和移动构造函数都不可用,语义检查将不能通过。

总而言之,符合优化条件但未遵守语言标准的代码绝不会因为能够被优化而通过语义检查。

编写支持统一初始化语法的 point

point 必须以两重括号的形式初始化总让人感觉不自然,我们可以尝试让它支持统一初始化语法,在前面的基础上需要保证三点:语法形式的支持、实参个数限制、窄化转换限制。

利用 std::initializer_list

我们来尝试一下利用 std::initializer_list

代码

template<typename T, std::size_t N>
struct point
{using value_type = scalar<T>;value_type _v[N];
point() : _v{ value_type{} } { }
template<typename U>explicit point(std::initializer_list<U> il){//static_assert(il.size() == N, "argument number mismatch.");//可行吗?//...} };

很快我们的尝试就遇到一个问题,如何在编译时限制传入 std::initializer_list 的长度。上述代码中这个静态断言会出现编译错误,编译器会提示 il.size() 不是编译期常量,不能用于静态断言环境。

std::initializer_list::size() 从 C++14 开始被标记为 constexpr,为什么它无法用于静态断言?这涉及 constexpr 函数的特性,constexpr 标识符声明一个返回值有可能在编译期求值的函数,但是它必须满足 编译期求值的条件。此处传入的这个 il 是一个运行期构造的变量,显然不符合编译期常量求值环境。

看来这条路走不通,得另寻他法。

可变参数模板构造函数

我们可以为 point 编写一个接受参数包的模板构造函数:

代码

template<typename T, std::size_t N>
struct point
{using value_type = scalar<T>;value_type _v[N];
point() : _v{ value_type{} } { }
template<typename... Args, typename = std::enable_if_t<sizeof...(Args) == N>>explicit point(scalar<Args>&&... args){//...} };

参数包展开中使用 scalar 限制参数为算术类型,这是为了防止这个模板函数被实例化为拷贝构造函数或者移动构造函数。在本例中即使不限制这个类型,也只在恰好 N == 1 时可能出现(实际的代码中创建一个一维点没什么意义),而且 explicit 的拷贝函数也很难匹配上大多数的拷贝语境,但是我在其他地方确实被这样的匹配坑过,这样的代码行为可能会让人意外,所以此处特意一提。

这个版本的构造函数已经能够很好地支持统一初始化语法和参数数量限制了,但是它还有一点未实现:限制数值窄化转换。

尝试实现 为了实现这个目标,我首先看了一下标准库是否直接提供这样的 traits,可惜并未找到,于是去网上搜索是否有什么实现思路,确实找到了一篇 博客 详细说明了实现思路,并指出关键点是 C++ 的拷贝列表初始化语法不允许窄化转换:

narrowing conversion

这段话让我大受启发,虽然这篇博客中实现的窄化检查是两个类型之间的,对它稍加改造就可以检测参数包了:

代码

//仅用于类型推导的空类
struct dummy { };
//单参数窄化转换检查辅助函数
template<typename T>
dummy narrowing_conversion_check(T);
//参数包窄化转换检查类,通过折叠表达式对参数包逐一进行窄化转换检查
template<typename T, typename... Args>
struct narrowing_conversion_guard : decltype(((narrowing_conversion_check<T>({ std::declval<Args>() })), ...)) { };
template<typename... Args, typename = std::enable_if_t<sizeof...(Args) == N>, typename = narrowing_conversion_guard<T, Args...>>//在point的构造函数中使用它 point(scalar<Args>&&... args) : _v{ std::forward<Args>(args)... } { }

发现已有机制 刚写完这个检测类我就恍然大悟,数组成员 _v 是直接支持列表初始化的,编译器自然而然会在列表初始化时进行窄化转换检查,所以在这种情况下没有必要手动检查,真是得来全不费功夫啊:

代码

template<typename T, std::size_t N>
struct point
{using value_type = scalar<T>;value_type _v[N];
point() : _v{ value_type{} } { }
template<typename... Args, typename = std::enable_if_t<sizeof...(Args) == N>>explicit point(scalar<Args>&&... args) : _v{ std::forward<Args>(args)... } { } };
point<int, 3> pi30{ 0, 1, 2 };//OK point<int, 3> pi31{ 0, 1 };//错误:需要3个参数,实际提供了2个参数 point<int, 2> pi2{ 1, 2.0 };//错误:列表初始化中无法将double窄化转换为int

对于一个空间点类,要么默认构造为全 0,要么指定所有元素的初值是合理的,因为这两种构造都符合一般直觉,并且空间点的维度 N 几乎不会取到大于 4,不会在逐一指定初值时造成编码负担。如果我们设计一个构造函数,它接受的参数数量可以不等于点的元素数量,并且没有给出注释说明在两者不相等时的构造行为,就会给使用者带来一些困扰并且可能造成被误用。

总结

作为一篇知识点整理笔记,本文内容写的比较杂,此处作一个简单总结:

1. 模板代码往往比普通代码需要更复杂的理解能力,所以在编写模板代码时,一些隐藏的语言规则问题更难被发觉;

2. 语义检查和代码优化的关系可以解释这样一个问题:为什么有些理论上会被执行的代码最终却没有被执行,既然没被执行,我们不定义(或阻止编译器生成)它们为什么又无法成功编译;

3. 正如 Scott Meyers, Effective C++, Item 18 所说,让接口容易被正确使用,不易被误用,花费时间琢磨如何设计更加符合普遍直觉且行为一致的接口是值得的。初始化作为基础中的基础,值得透彻研究,这有助于设计语义清晰,更易被正确使用的接口;

相关文章:

C++ 模板参数推导问题小记(模板类的模板构造函数)

本篇主要是为了记录在编写一个模板类的模板构造函数中遇到的初始化问题,以及针对这个问题展开的相关知识整理,文章就以引发这个问题的代码为标题了。 问题代码 在编写一个代表空间点的模板类 point 时,我打算为它添加一个模板构造函数:代码template<typename T, std::si…...

axios两种写法

// 登录 export const login = (data) => {return request.post(/login, data) }// 权限管理列表 get请求需要写在url上面 export const authAdmin = (params) => {return request.get(/auth/admin, { params }) } ///////////////////////////////////////////////////…...

adobe illustrator中使用画笔工具切割图形

001、测试图形 002、选择画笔工具 3、绘制想要切合的形状,然后同时选中这跟线和图形 004、窗口 + 路径查找器 005、 点击分割 006、 点击取消编组 007、 实现图形分割 。...

2025年了,在 Django 之外,Python Web 框架还能怎么选?

前言 大家好,我是曦远~ 前段时间我写过一篇文章 《Django过时了吗?从ASGI到AI时代的思考》,聊到在 AI 时代下,传统全家桶式框架(比如 Django)该如何面对新趋势。 最近在翻新 DjangoStarter 项目的时候,我顺便做了一些调研,发现 Python Web 生态的变化比我想象得还要快。…...

AtCoder Beginner Contest 423

D - Long Waiting 三个优先队列 #include<bits/stdc++.h> using namespace std; #define endl \n #define yes cout << "YES" << endl #define no cout << "NO" << endl #define pii pair<int,int> #define ll long l…...

SRAM和DRAM的特点和区别

SRAM 静态随机存取存储器 基本结构和工作原理:核心单元:SRAM每个cell 由6 个晶体管 组成,形成一个双稳态触发器电路。 工作原理:这种电路结构由两个稳定的状态,分别代表逻辑“0”和逻辑“1”。只要保持通电,状态就会一直保持下去,不需要额外的操作。 读写过程:通过字线…...

xml基本语法

1. xml的基本结构 XML(可扩展标记语言,eXtensible Markup Language)是一种用于存储和传输结构化数据的标记语言,核心特点是自定义标签和严格的语法规则.一个合法的 XML 文档必须包含文档声明和唯一根元素<?xml version="1.0" encoding="UTF-8"?&g…...

Java25新特性

🛠️ 1. 语言特性与开发者体验实例主方法 (Instance Main Methods)​: 支持省略 public static修饰符的 void main()方法,使初学者更易编写第一个Java程序。// 无需显式类声明和public static修饰符 void main() {IO.println("Hello, JDK 25!"); // java.lang.IO …...

Day17多维数组

多维数组可以看成数组的数组,即在数组中在嵌套一个数组 例如二维数组是一个特殊的一维数组,他的每一个元素都是一个一维数组(1,2,3,4,5.......) 格式与一维数组相似:int [] [] a = new int [i] [j]; 举例的二维数组可以看为两行五列的数组 public class ArrayDemo5 {pub…...

C++ lambda 匿名函数

1、基本介绍 C++11 引入的 lambda 匿名函数(Lambda Expression)是一种轻量级的函数对象,可在需要函数的地方直接定义,无需单独声明,极大简化了代码编写(尤其是回调函数、算法谓词等场景)。 基本语法: [capture-list] (parameter-list) mutable noexcept(optional) ->…...

D拼数

include<stdio.h> include<stdlib.h> #include<string.h> int compare(const void *a, const void *b) { char str1[40], str2[40]; // 1:a在前,b在后 sprintf(str1, "%d%d", *(int *)a, *(int *)b); // 2:b前a后 sprintf(str2, "%d%d&q…...

20250917 - WETToken 攻击事件:价格操控产生的套利空间

背景信息Alert:https://x.com/TenArmorAlert/status/1968223320693686423 TX:https://app.blocksec.com/explorer/tx/bsc/0xf92539acf7eadfd4a98925927a52af5349cb13c2a250908373a5baf8ea4b49adTrace 分析 发生攻击的位置在闪电贷的 callback 函数里面,执行完闪电贷后攻击合…...

题解:P6798 「StOI-2」简单的树

简单的树: 题意: 一颗树,每个节点有一个权值 \(c_i\)。 \(val_i\):\(i\) 为根的子树内所有 \(c_i\) 的最大值。 \(f(x,y)\):\(c_{x}\) 改为 \(y\) 后 \(val_i\) 之和。 每次询问给定 \((l,r,a)\) ,求 \(\sum\limits_{i=l}^{r}{f(a,i)}\)。 思路 首先一眼看出来几个性质:…...

题解:P11704 [ROIR 2025] 旅行路线

旅行路线: 很有参考价值的一道题,其他题解有点抽象,我来。 转化题意 题意转化为 \((1,2)→(n-1,m),(2,1)→(n,m-1)\) 的两条链不相交且经过所有关键点的方案数。 其他点没用,我们以下的点指关键点。 无不能相交限制的 DP 由于 \(x_i\le x_j,y_i\le y_j\),\(i\) 才可以转移…...

题解:P11292 【MX-S6-T4】「KDOI-11」彩灯晚会

彩灯晚会:\(n\) 点 \(m\) 边 \(k\) 种颜色,给每个点染色。 \(cnt_i\):第 \(i\) 种颜色长度为 \(l\) 的链的数量。其中 \(l\) 为题目给的一个常量。 求 \(\sum_{染色方案}\sum_{i=1}^k cnt_i^2\) 的和。一\(\sum_{染色方案}cnt_i\) 值都一样,钦定 \(pos\) 作为代表颜色,那么…...

算法课程第一周作业

《数学之美》第一章启示 《数学之美》的第一章,在算法工程师眼中,并非传授某个具体算法.而是重构了我们理解、设计和应用算法的底层思维框架,世界的基本问题是算法问题,而数学是寻找最优算法的终极语言。 启示一:所有问题本质上都是建模与算法选择问题.意味着世界是一个巨大的待…...

实测对比:权威榜单之微信排版Top 5编辑器大揭秘

在新媒体运营的世界里,微信排版可是重中之重,它直接影响着文章的视觉效果和读者的阅读体验。很多运营人都有这样的痛点:写作慢、排版耗时、跨平台排版不统一、配图难还可能有侵权风险等。为了帮大家解决这些难题,我亲测了有一云AI编辑器、智撰AI编辑器等多款主流编辑器。在…...

自建仓库推送到NAS采用 Docker Registry 工作流

放弃手动 `save` 和 `load` 的方式,改用行业标准的 Registry(仓库)模式。这是最专业、最高效的方案。 **优点**: - **彻底解决版本兼容性问题**,因为 push/pull 协议是标准化的。 - 传输效率高,再次推送时只会上传有变动的层(layer)。 - 是 DevOps 和自动化流程的基础,…...

【汇编和指令集 . 第2025 . 9期】发现大牛

【编者按】在计算机、互联网风行半个世纪之后,我们发现:科技预言家越来越多了,思想家缺位了。生活节奏变快了,思想退步了;书写减少了,纸张缺没少;知识泛滥了,思考没有深入......我们有可能遭AI时代的反噬。时代呼唤跨文理的大家,呼唤有温度的电子产品。发刊词: …...

Opencompass避坑日记

安装首先执行pip安装 再下载源代码第一句是为了安装opencompass的依赖包,第二句是为了在当前目录引入本地目录的opencomass模块。 因为有很多修改的地方。 测评VLLM 放弃吧,这个框架对VLLM的支持很差。测评方式:稳定的有且只有这一种python run.py \--datasets demo_gsm8k_c…...

随笔 | 农场、小猴子、香蕉

在一个偏西部的农场中,有着一群猴子,他们每天的任务,是将香蕉树上的香蕉摘下来,而他们的报酬是仅仅九根香蕉,每天早上四根,每天晚上五根。某一天,其中一只猴子报怨,每天早上只能吃到四根香蕉,他提议说,改成每天早上五根香蕉,其他猴子都纷纷表示同意,仅有一只小猴子…...

Day17数组的使用

package com.cc.array;public class ArrayDemo4 {public static void main(String[] args) {int [] arrays = {1,2,3,4,5};//jdk1.5之后的版本可以通果增强for寻循环来遍历数组或集合中的每一个元素//缺点在于没有下标//for(int array:arrays){// System.out.println(array);p…...

完整教程:缓存与数据库一致性的4大坑及终极解决方案

完整教程:缓存与数据库一致性的4大坑及终极解决方案pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monosp…...

Rust的Cargo用法详解 - 详解

Rust的Cargo用法详解 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-si…...

串行通信接口标准(TTL、CMOS、RS232、RS422、RS485、CAN等)

TTL电平 引言 TTL是 Transistor-Transistor Logic(晶体管-晶体管逻辑)的缩写,是早期基于双极性晶体管(BJT)技术的逻辑家族。 电平特点 1. 电源电压:+5V 2. 电平标准:Voh:≥ 2.4V; Vol: ≤ 0.4V; Vih:≥ 2.0V; Vil: ≤ 0.8V;核心特点: 1. 输入悬空:TTL输入引脚如…...

攻防世界-IgniteMe - xxx

先查壳,发现没加壳,拖入ida-32反汇编了得到主函数 粗略看一下,能得到的信息有 输入的字符串长度为29,前四个字符是EIS{,最后一个字符是}想要输出Congratulations!关键的函数就是这个 4011C0函数,我们点进去看一下函数逻辑很明显,for循环之前就是把之前输入的字符串str除…...

C 语言 之 面向对象(一)

C 语言 之 面向对象(一)C 语言 之 面向对象(一) 了解C语言面向对象之前首先需要对C语言的指针、结构体有基本了解。 指针 正常使用数组: void hello(){#define count 10// shint a[count] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};for(int i = 0; i < count; i ++ ){printf(…...

for_switch

func forCase() {for i := 0; i < 10; i++ {if i == 5 {continue}fmt.Println("位置1 执行 for 语句块 i:", i)}fmt.Println("-------循环 slice ------")list := []int{1, 2, 3, 4, 5}for index, value := range list {fmt.Println("循环切片 执…...

快速幂

前题引入 我们平时用的pow函数速度太慢了怎么办,我就就需要快速幂(意思废话) 题目分析 前题铺垫 你只是需要知道一个非常简单的东西 a^b + a^c =a^(b+c) 思路 既然暴力是O(b)的,那我们是不是可以考虑O(log b) 那我们尝试将b除以2 那么就可以知道a^b = a^b/2 + a^b/2 但是我…...

模拟退火

#include<bits/stdc++.h> using namespace std; double kai=10000,eps=1,jiang=0.92,fw;//fw 记得赋值 mt19937 rd(time(0)); #define bu t*(rd()%(2*(int)fw)*1.0-fw) #define gl 1.0*rand()/RAND_MAX int ans,sx;//题目要求时开 double int cha(int x) {/**/return a…...

记录我见过的神人

魔丸《待审核》 注:团长高仿号申请进团焯神观察兵古风 古风...

DOS指令学习

打开CMD的方式 1.开始+系统+命令指示符 2.Win键+R 输入cmd 打开控制台(推荐使用) 3.在任意的文件下面,按住shift键+鼠标右键点击,在此处打开命令窗口 4.资源管理器的地址栏前面加上cmd路径 管理员方式运行:选择以管理员方式运行 常用的Dos命令 #盘符切换 #查看当前目录下的…...

【Azure环境】使用ARM Template部署Policy模板时候报错不支持filed函数: The template function field is not valid.

问题描述 Azure Policy可以帮助治理Azure上的资源, 也可以通过ARM 模板部署。只是当Policy中包含了field 函数的时候,会出现错误!"parameters": {"keyVaultName": {"value": "[field(name)]"}} 错误信息:Unable to process temp…...

CDQ分治

一、解决偏序问题 不言即默认非严格偏序问题。 严格偏序,未有此题。 若汝要学,小点三维。 同 \(a\) 者并,\(b\) \(c\) 小改。 幸甚至哉,歌以咏志。 三维偏序 按第一维排序,通过只计算左对右造成的贡献来满足第一维偏序条件。 第二维对于左右两个区间分别独自按第二维排序然…...

开源AI大模型、AI智能名片与S2B2C商城小代码:从“不出现=不存在”到“精准存在”的数字化转型路径

开源AI大模型、AI智能名片与S2B2C商城小代码:从“不出现=不存在”到“精准存在”的数字化转型路径pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mo…...

202509 组合数学与计数类 DP 笔记

1. P2051 [AHOI2009] 中国象棋 一格一格进行考虑做 DP 想不出来,考虑到一行实际上只需要选两格进行操作,因此可以一行一行操作。 设 \(f_{i,j,k}\) 表示考虑到第 \(i\) 行,有 \(m-j-k\) 列有 \(0\) 个棋子,有 \(j\) 列有 \(1\) 个棋子,有 \(k\) 列有 \(2\) 个棋子。边界条…...

edu 106 E(LCS dp + 多源bfs优化)

E 先考虑对两个固定串怎么做:可以确定形成串的末尾一定是 \(a_{i}\) 或者 \(b_{j}\),直接子序列 \(dp\) 即可:\(dp_{i,j,0/1}\) 表示只考虑 \(a\) 长度为 \(i\) 的前缀和 \(b\) 长度为 \(j\) 的前缀,\(0\) 表示形成的串以 \(a_{i}\) 结尾;\(1\) 表示形成的串以 \(b_{j}\) …...

ABC310E NAND repeatedly 题解

https://atcoder.jp/contests/abc310/tasks/abc310_e 一个奇怪的递归式 + \(N \le 10^6\), 试试动态规划 设 \(dp_{i,j}\) 为对于所有 \(1 \le l \le i\) 满足 \(f(l, i)=j\) 的数量, 其中 \(j \in \{0,1\}\). 最后答案就是 \(\sum\limits_{i=1}^{n}dp_{i,1}\) 分情况讨论:当 \…...

MyBatis插入语句配置

MyBatis 插入语句配置 <sql id="Manage_field"> id,userName,passWord,realName</sql> <!-- 实体类属性--><sql id="Manage_insert">#{id},#{userName},#{passWord},#{realName}</sql><insert id="insert" …...

操作运算符

package _caseimport "fmt"// 关系运算 func RelationCase() {var a = 21var b = 10fmt.Println("a == b", a == b)fmt.Println("a != b", a != b)fmt.Println("a > b", a > b)fmt.Println("a < b", a < b)fmt.…...

看 NOI2025 游记记

我很久以前看过 50+ 篇让我印象深刻的 NOI 游记,里面有句话让我在看游记前的某次梦里想起:“看游记好爽,心潮在荡漾”。 Day0(2025.7.31) 状态不是很好,看了几篇游记复习了一下。 Day1(2025.8.1) 早上 6:15 起床,6:30 到机房,老师宣读早读板子,登上洛谷,我迅速打开…...

整体二分

前言 注意:以下的 “元素” 都代表原题中的一个操作。 大说 把当前值域一分为二,把当前元素集合,每个元素的决策只有左区间 or 右区间,可以把同决策的元素放在一起去分治子区间(类似于线段树的结构)。 如下图(左边是值域区间,右边是元素集合):上图每个询问的答案: ①…...

得力 - Bruce

@echo off title Win10 游戏下载速度优化脚本 echo ===================================== echo Win10 游戏下载慢 - 优化工具 echo (请以管理员身份运行) echo ===================================== echo.:: 关闭 Windows 更新的传递优化 echo [1/6] 正在关闭 Windows …...

短视频营销运营导师张伽赫,绳木传媒AI+短视频引领企业数字化变革

在当下企业数字化转型的浪潮中,短视频营销已成为关键赛道。张伽赫,这位深耕短视频领域十年的实战派导师,同时也是东莞绳木传媒的创始人,凭借 “AI+短视频” 的创新模式,在行业内异军突起,为众多传统企业提供了数字化转型的全新思路与解决方案。一、方法论革新:从流量思维…...

详细介绍:还在重启应用改 Topic?Spring Boot 动态 Kafka 消费的“终极形态”

详细介绍:还在重启应用改 Topic?Spring Boot 动态 Kafka 消费的“终极形态”pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "C…...

用 TensorFlow 和 CNN 实现验证码识别

在本教程中,我们将使用 TensorFlow 和 卷积神经网络(CNN) 来构建一个验证码识别系统。TensorFlow 是一个流行的深度学习框架,支持构建和训练神经网络。通过构建卷积神经网络(CNN),我们可以自动从图像中提取特征并执行字符分类任务。环境准备首先,我们需要安装 TensorFl…...

用 PyTorch 和 CNN 进行验证码识别

在本教程中,我们将使用 PyTorch 和 卷积神经网络(CNN) 来构建一个验证码识别系统。PyTorch 是一个广泛使用的深度学习框架,特别适合研究和原型设计。卷积神经网络(CNN)是处理图像数据的强大工具,它可以自动从图像中学习特征,并执行图像分类等任务。环境准备首先,确保你…...

用 Keras 和 CNN 进行验证码识别

在本教程中,我们将利用 Keras 和 卷积神经网络(CNN) 来构建一个验证码识别系统。Keras 是一个高层神经网络 API,它运行在 TensorFlow、Microsoft Cognitive Toolkit(CNTK)或 Theano 之上,能够让我们快速构建深度学习模型。CNN 是一种常用于图像识别任务的深度学习架构,…...

从 Bank Conflict 数学表示看 Buffer 设计 Trade-Off

在并行处理器设计中,我们希望最大化访存吞吐,让更多的数据分布在不同的 bank,而非在一个 bank 中产生堵塞。一种场景是面对多应用并行,这往往可以通过划分上下文基地址隔离;而另一种场景则是高并行同一个数据共用基地址,本文针对该场景下常见情形 Tensor Data Layout 进行…...

被彼此笼罩 任泪水将我们缠绕 深陷入恶魔的拥抱 在阴冷黑暗处灼烧 吞下这毒药

方格染色grid 不难发现按着行顺着来,odt 那样维护即可。数字图graph 为什么本可做这个题做了很久(? 首先显然可以二分降低难度,然后就是观察。...