首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

未来已来:从SFINAE到concepts

这是一种 C++ 中编译期技术,用于在模板实例化过程中,当尝试进行模板参数替换时,如果出现了替换失败(通常是由于找不到相应成员函数、操作符等),不会导致编译错误,而是会选择其他可行模板特化。...std::enable_if 就是利用了 SFNIAE 概念,通过在模板参数替换失败时移除特化,实现了在编译期间条件选择。...在前面的例子中,我们无非是通过各种方式来约束参数,使得满足某个条件参数调用一个模板函数,而不满足使用另外一个模板函数。这种方式在C++20用更为广泛,称之为约束模板参数。...: template void fun(T x) { // ... } 这样当传入fun()int类型时候,编译器会报如下错误: : In...Concepts 允许程序员定义对类型进行断言语法,这样在模板中可以使用这些断言来约束模板参数,使得只有满足特定条件类型才能匹配模板

13810

C++雾中风景17:模板推断语境与std::type_identity

1.推断语境 众所周知,函数模板使用是C++编译期进行类型推导过程。通过分析源代码之中函数实参类型,进一步推断出调用函数参数类型,从而自动生成对应函数,来达到精简代码逻辑效果。...而所谓推断语境呢?则是模板类型不参与模板实参推导,取而代之地使用可在别处推导或显式指定模板实参。 单看上述文字可能很难理解,咱们直接看代码就能明白了。...那我们就需要利用推断语境来解决问题了,让val类型不要参与到类型推导过程之中来,那么问题就解决了。 模板推断语境出现比较复杂,有需要可以参考cppreference部分详细解释。...正是因为推断语境在模板推断中会被使用,所以C++20提供了新trait: std::type_identity与std::type_identity_t来帮助我们解决上述问题。...它们实现与功能与上面展示identity一致,都是利用模板推断语境来规避类型推断不同导致编译失败问题。

68730
您找到你想要的搜索结果了吗?
是的
没有找到

C++雾中风景18:C++20, 从concept开始

std::is_same_v); static_assert(!...std::is_same_v进行一个其实没什么意义类型比较,来满足static_assert语义,最终满足我们对模板类型T一些约束。...requires后面可以带任意concept concept使用 了解了concept定义之后,我们就可以利用concept来进行模板类型约束了。...concept很简单,它只是C++20给你提供一个better工具,来摆脱被疯狂模板报错所支配恐惧。但即使你完全不了解它,使用方式,依然能够同样解决问题。...而很多时候我们使用它需要 要进行模板推断类型编程设计 利用SFINAE方式来类型约束 这无形之中增加Coding时心智成本,而concept作为一个新语法糖,给了我们拆分二者机会:让上帝归上帝

59030

C++雾中风景17:模板推断语境与std::type_identity

1.推断语境 众所周知,函数模板使用是C++编译期进行类型推导过程。通过分析源代码之中函数实参类型,进一步推断出调用函数参数类型,从而自动生成对应函数,来达到精简代码逻辑效果。...而所谓推断语境呢?则是模板类型不参与模板实参推导,取而代之地使用可在别处推导或显式指定模板实参。 单看上述文字可能很难理解,咱们直接看代码就能明白了。...那我们就需要利用推断语境来解决问题了,让val类型不要参与到类型推导过程之中来,那么问题就解决了。 模板推断语境出现比较复杂,有需要可以参考cppreference部分详细解释。...正是因为推断语境在模板推断中会被使用,所以C++20提供了新trait: std::type_identity与std::type_identity_t来帮助我们解决上述问题。...它们实现与功能与上面展示identity一致,都是利用模板推断语境来规避类型推断不同导致编译失败问题。

1K10

C++雾中风景18:C++20, 从concept开始

std::is_same_v); static_assert(!...std::is_same_v进行一个其实没什么意义类型比较,来满足static_assert语义,最终满足我们对模板类型T一些约束。...requires后面可以带任意concept concept使用 了解了concept定义之后,我们就可以利用concept来进行模板类型约束了。...concept很简单,它只是C++20给你提供一个better工具,来摆脱被疯狂模板报错所支配恐惧。但即使你完全不了解它,使用方式,依然能够同样解决问题。...而很多时候我们使用它需要 要进行模板推断类型编程设计 利用SFINAE方式来类型约束 这无形之中增加Coding时心智成本,而concept作为一个新语法糖,给了我们拆分二者机会:让上帝归上帝

1.1K00

C++模板取函数参数类型和返回值类型方法

参考链接: C++编程默认参数(参数) 假设要利用模板元编程获取位于index参数类型:  template struct ArgTypeAt...= ArgTypeAt::type; // 假设这样使用模板  这时FunctionType就是一个单独类型int(int, short, float)了,里面含有各参数类型...要把FuntionType分离成返回值类型和参数类型,方法是利用模板特化,然后参数类型是一个包,再把参数包展开就能得到各位置参数类型:  template<int index, class FuntionType...(默认是__cdecl)改成__stdcall这个模板特化就不匹配了,因为修饰符也是类型一部分,而C++泛型并没有修饰符变了还能匹配方法(只有类型变了能匹配)。...参考标准库std::function定义了一堆宏,我也用宏改造成下面这样:  template struct ArgTypeAt; #define

4K50

c++模板使用

a : b; } 模板特例化 模板特例化和模板重载函数可以共存,编译期针对不同数据类型,生成多个版本函数,c++11之后可以使用constexpr常量表达式,写编译期代码 template class...template class Thing> class Crab{} Crab a;//使用模板作为类模板 函数模板参数 template...内部类型 std::is_same_v 变量 std::remove_reference::type 变量 std::enable_if::type 条件满足返回类型...,不满足无类型编译错 decltype 编译期获取变量类型 std::declval 推到模板T对象值 if constexpr () 编译期条件判断,根据constexpr内部生成多条代码...模板执行在编译器,所以模板成员只要传入参数匹配,写固定成员变量,只要编译过了也是可以

71320

高效使用stl::map和std::set

1、低效率用法 // 先查找是否存在,如果不存在,则插入 if (map.find(X) == map::end()) // 需要find一次 {     map.insert(x); // 需要find...if (map.count(X) > 0) // 需要find一次 {     map.erase(X); // 需要find一次 } else {     // 不存在时处理 } 2、高效率用法...// 解决办法,充分利用insert和erase返回值,将find次数降为1 map::size_type num_erased = map.erase(X); // 需要find一次 if (0...== num_erased) {     // 不存在时处理 } else {     // 存在且删除后处理 } pair result_inserted; result_inserted = map.insert...(X); if (result_inserted.second) {     // 不存在,插入成功后处理 } else {     // 已经存在,插入失败后处理     result_inserted.first

2.9K20

函数模板与同名模板函数不可以重载(重载定义)

当其它要素都相等时,重载机制将优先选择调用函数模板而不是函数模板【对于这个问题,个人觉得可能是基于如下原因:进行重载将降低程序效率,对函数模板是如此,对于更为复杂函数模板更是如此(至少还需进行一次实例化...),因此重载机制将优先选择调用函数模板而不是函数模板。】。...那些无法跟函数模板进行最佳匹配,则调用函数模板实例化对象,如第一和第二个函数调用。...【三】、对于最后一个函数调用max( ‘a’, 42.7 );一开始我认为是调用函数模板,结果确实也是调用了函数模板,我理由是两个参数类型明显不同,后面看到书上解释,是这么说:自动类型转换,...只适用于一般函数(即函数模板)。

84220

日更系列 - 又一次碰到线程安全std容器core

众所周知,std容器是非线程安全,跟线程安全容器,如果代码core掉,通常会在容器一些方法函数中。因为这类core文件往往显示不是很直观,很多c++ std新手往往对这类型core无从下手。...最后汇聚所有场景打分信息。 二、问题复现 有一天,开发代码进行了灰度发布,隔一段时间会有个core文件。使用gdb打印了信息如下。...v消息20220602-170753 (2).jpg 把m_cvr2内容进行了打印(因为容器元素很多,这里使用了gdb内置命令set logging on,将std out屏幕输出写份副本到文件名gdb.txt...那么后续线程并发访问使用operator[index]操作都有现成元素可以使用。这里类似m_ctr和m_cvr,把元素都初始化预填充出来。...所以总结一些使用std容器一些准则, 并发使用不新增元素(这里元素如果是简单类型pld是允许,而非pld类型,如string或者各种类结构体是不允许使用前在同一线程进行预填充。

94320
领券