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

C++那些事之SFINAE

根据名称找出所有适用函数函数模板对于适用函数模板,要根据实际情况对模板形参进行替换; 替换过程中如果发生错误,这个模板会被丢弃 在上面两步生成可行函数集合中,编译器寻找一个最佳匹配,产生对该函数调用...一个简单函数调用,如“f(obj);”在c++中,激活一个机制,根据参数obj确定应该调用哪个f函数。...2.2 SFINAE 回忆一下上述重载决议: 函数调用 函数模板 SFINAE 我已经用几个段落强大功能来戏弄你了,现在终于可以解释这个并不复杂缩写词了。...在某些情况下,如果替换导致无效代码,编译器不应该抛出大量错误,而应该继续尝试其他可用重载SFINAE概念只是为“健全”编译器保证这种“健全”行为。...它只是尝试下一个重载。 再来回顾一下上述简单理解:替换就是尝试用提供类型或值替换模板参数机制。在某些情况下,如果替换导致无效代码,编译器不应该抛出大量错误,而应该继续尝试其他可用重载

2.2K20

现代C++之SFINAE

根据名称找出所有适用函数函数模板对于适用函数模板,要根据实际情况对模板形参进行替换; 替换过程中如果发生错误,这个模板会被丢弃 在上面两步生成可行函数集合中,编译器寻找一个最佳匹配,产生对该函数调用...一个简单函数调用,如“f(obj);”在c++中,激活一个机制,根据参数obj确定应该调用哪个f函数。...2.2 SFINAE 回忆一下上述重载决议: 函数调用 函数模板 SFINAE 我已经用几个段落强大功能来戏弄你了,现在终于可以解释这个并不复杂缩写词了。...在某些情况下,如果替换导致无效代码,编译器不应该抛出大量错误,而应该继续尝试其他可用重载SFINAE概念只是为“健全”编译器保证这种“健全”行为。...它只是尝试下一个重载。 再来回顾一下上述简单理解:替换就是尝试用提供类型或值替换模板参数机制。在某些情况下,如果替换导致无效代码,编译器不应该抛出大量错误,而应该继续尝试其他可用重载

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

现代C++之SFINAE应用(小工具编写)

一样简单,但这背后实现也就仅仅不到100行代码,本节实现这种功能。...2.是否存在输出函数 使用SFINAE检测是否可以直接输出: // 检测是否可以直接输出 template struct has_output_function { template...若可以直接输出,那就调用系统输出了,否则调用后面自己写,因此后面目标变为:针对没有输出函数容器调用自己编写输出函数。...3.针对没有输出函数容器处理 通过enable_if_t限定调用<<重载操作符是针对没有输出函数容器,内部逻辑很简单,第一次只输出元素,后面就输出,与元素,也就是用,分割元素,最后就是比较重要output_element...下面原理还是SFINAE实现,当不是pair时候就调用第二个重载函数了,否则就是第一个。

1.1K20

C++ 模板沉思录(上)

这种方案缺点也很明显:其使得代码写起来像“汇编语言”(movl,movq,...)。我们需要针对不同类型调用不同名称函数(是的,C语言也不支持函数重载),这太可怕了。...模板实例化具有一个非常重要特征:惰性。这种惰性主要体现在类模板上。...当遇到这种情况时,C++做法十分宽松:不完美?不要紧,只要不调用那些“不完美的函数”就行了。...那么,为什么不直接使用形如“T()”这样写法,而需要声明一个“稻草人函数”呢?...也就是说,如果我们给这一对重载函数传入一个A类型值时,由于“...”参数重载确定优先级低于其他一切可行重载版本,只要A到B隐式类型转换能够发生,重载确定结果就一定是调用第一个版本函数,返回值为

1.3K20

浅谈 C++ 元编程

然后根据 SFINAE 规则: 使用 std::enable_if 重载函数 ToString,分别对应了数值、C 风格字符串和非法类型; 在前两个重载中: 分别调用 std::to_string 和...这会导致:两次绑定中,有一次失败。...一般思路是:提供两类重载 —— 一类接受 任意参数,内部 递归 调用自己;另一类是前者 模板特化 或 函数重载,直接返回结果,相当于 递归终止条件。它们重载条件可以是 表达式 或 类型。...函数 Sum 有两个重载:一个是对没有函数参数情况,一个是对函数参数个数至少为 1 情况。和定长模板迭代类似,这里也是通过 递归 调用实现参数遍历。...另外,编译时模板实例化出错位置,在调用层数较深处时,编译器提示每一层实例化状态,这使得报错信息包含了很多无用信息,很难让人较快发现问题所在。

2.9K60

C++模版本质

C++模板实现 C++标准委员采用一套类似函数式语言语法设计C++模板,而且设计成图灵完备 (Turing-complete)(详见参考),我们可以把C++模板看成是一种新语言,而且可以看成是函数式编程语言...这发生在尝试调用函数、取函数模板地址时,和某些其他语境中; 函数模板在进行实例化后会进行函数重载解析, 此时函数签名不包括返回值(template argument deduction/substitution...); 函数模板实例化过程中,参数推导不匹配所有的模板或者同时存在多个模板实例满足,或者函数重载决议有歧义等,实例化失败; 为了编译函数模板调用,编译器必须在非模板重载模板重载模板重载特化间决定一个无歧义最佳模板...模板多个实例很有可能隐式增加二进制文件大小等,所以模板在某些情况下有一定代价,一定要在擅长地方发挥才能; 如何降低门槛,对初学者更友好,如何降低复杂性,这个是C++未来发展重要方向。...曾经递归变成了普通constexpr函数,曾经SFINAE变成了concept,曾经枚举常量变成了constexpr常量,曾经递归展开变成了fold expression,越来越简单,友好了。

1.7K30

C++20初体验——concepts

这些是句法上无法检查,所以这两个concept更像是一种规约:如果模板参数被这种concept约束,那么客户调用时传入参数就得满足这些语义需求。...函数模板与类模板约束是类似的,只有满足约束时模板才能实例化;对于成员函数约束,如果它作用于模板模板参数,当约束不满足时,并不是类模板不能被实例化,而是实例化后模板类没有这个成员函数: #include...);唯独第三条没有解决,导致冗长模板错误,并且衍生出以SFINAE为代表一些奇技淫巧。...根据SFINAE,test调用落入two test(...)...模板类型发生错误,根据SFINAE,该重载被忽略;与此同时第二个是可用

1.3K10

C++设计模式之SFINAE:用来检测类中是否有某个成员函数

SFINAE是Substitution Failure Is Not An Error缩写,直译为:匹配失败不是错误。属于C++模板编程中高级技巧,但属于模板元编程中基本技巧。...举个例子,我们check一下C++标准库类中有没有push_back()成员函数。...而test函数,对于返回true模板函数,其参数是一个指针类型。所以实际check时候,传入一个NULL就可以匹配到。...如果需求是要检测任意成员函数,而不限定是哪个函数的话,毫无疑问,需要借助宏了。将上面的代码改变成宏版本,push_back作为宏一个参数,即可。 我这里为什么用push_back()举例呢?...当然C++11之前版本,需要你能枚举出push_back各种参数种类才行,若待检测成员函数重载版本比较多时候,则可能很麻烦。所以还是C++11之后版本简洁且通用。

3.4K20

【笔记】《深入理解C++11》(上)

不但可以调用基类构造函数, 也可以调用当前类其他构造函数, 这样就能进一步减少重复代码 但要注意委派构造不能和普通初始化列表共用, 因为目标构造(初始化列表)总是先于委派构造被调用, 这会导致目标构造参数无效...其他构造函数通过带有默认值委派构造调用这个目标构造函数 千万小心环形委派, 导致编译错误 委派构造函数使得构造函数模板编程也成为一种可能, 通过让模板构造函数成为委派构造函数, 我们可以很容易地接受多种不同类型参数进行相同底层初始化...大括号初始化制止类型收窄 大括号返回值是initializer_list, 可以用作函数一种重载参数 大括号也可以在return, 一般用来构造临时变量, 具体构造出来临时变量还是依靠声明返回值决定...C++11给namespace引入了inline关键字, 经过inline名称自动内联展开到上层, 从而破坏名称空间封装 因此建议还是尽量用打开空间方法使用 SFINEA规则 SFINAE:...函数模板是根据我们实参类型在调用时进行特化并实例化, 具体来说匹配遵循以下步骤: 首先对于一次调用, 编译器查找所有具有此名称函数和实例化模板函数表 在这些函数中进行比较, 将不可行函数剔除,

1.8K20

未来已:从SFINAE到concepts

,将参数x赋值给一个string类型v,但是在main()函数中 ,调用fun()函数时候传入了1,这个编译器推导为int类型,那么把一个int类型赋值给string,编译器会报错。...这是一种 C++ 中编译期技术,用于在模板实例化过程中,当尝试进行模板参数替换时,如果出现了替换失败(通常是由于找不到相应成员函数、操作符等),不会导致编译错误,而是会选择其他可行模板特化。...它核心思想是,如果在模板参数替换中遇到了错误,编译器不应该报错,而是应该简单将这个特化从候选列表中移除。这样,即使部分模板特化失败,编译仍然可以继续进行,选择其他可行特化。...在前面的例子中,我们无非是通过各种方式约束参数,使得满足某个条件参数调用一个模板函数,而不满足使用另外一个模板函数这种方式在C++20用更为广泛,称之为约束模板参数。...Concepts 允许程序员定义对类型进行断言语法,这样在模板中可以使用这些断言约束模板参数,使得只有满足特定条件类型才能匹配模板

14210

C++之函数重载

函数重载是:函数名相同,但是函数参数不同函数之间关系。函数重载只能通过函数参数不同来实现,这包含参数个数不同和参数类型不同。 !!! 重载不是面向对象特征。...事实上C++是支持模板函数。我们也可以使用模板函数来实现参数个数相同重载函数功能。 当然了,main函数是不能被重载。它是留给操作系统接口。...函数重载是根据函数参数来匹配函数,因此匹配可能出现下面的几种结果: 1.完全匹配,调用成功。编译器自动寻找最佳匹配调用。 2.参数不匹配,调用失败。...3.存在多个与实参匹配函数调用具有二义性。这种情况发生一般是由于参数隐式类型转换或者是重载函数函数参数具备默认值。...:f(3);这时候编译器告诉你对重载函数调用不明确

72620

C++ 学习笔记

a : b; } 1.5 函数模板重载 1.一个非模板函数可以和同名函数模板共存,并且函数模板可实例化为和非模板函数具有相同类型参数函数函数调用时,若匹配度相同,将优先调用模板函数。...(替换失败不是错误) SFINAE:当函数调用备选方案中出现函数模板时,编译器根据函数参数确定(替换)函数模板参数类型及返回类型,最后评估替换后函数匹配程度。...普通函数模板函数也可以同时重载,此时在匹配程度相同时,优先调用普通函数。...} 16.3 显式特化 重载只适用于函数模板,对于类模板,可以使用特化方式使得编译器进行更优选择。...萃取 可以基于 SFINAE 原理排除某些重载函数模板

6.6K63

C++奇淫巧技之SFINAE

SFINAE 技术,即匹配失败不是错误,英文Substitution Failure Is Not An Error,其作用是当我们在进行模板特化时候,会去选择那个正确模板,避免失败 看个具体例子...,会去匹配模板 multiply,但是由于我们不知道multiplication_result,根据 Substitution Failure Is Not An Error ,于是我们就去选择函数 multiply...这种技术在代码中一个大用途就是在编译时期确定某个 type 是否具有我们需要性质,看代码 template struct is_pointer { template...FooMemberPtr>::value); // prints 1 printf("%d\n",is_pointer::value); // prints 1 } 通过定义4个重载...is_ptr函数,3个是接受不同指针参数,另一个则包括了其他所有参数, IntPtr 是一个变量指针 FooMemberPtr 是一个成员属性指针 FuncPtr 是一个函数指针 接着我们来看下

51430

实际工程中 C++ 模板

模板常被当作洪水猛兽一个原因是许多人提起模板就要提 C++ 模板图灵完备,甚至还要再秀一段编译期排序,这种表现模板强大方式不仅不会让人觉得模板有用,反而让人觉得模板难以理解而且不应该使用。...我们当然可以对每个配置项类型都实现一个函数重载,但是我们也可以使用函数模板来生成这些代码,非常简单: template bool IsAvailableVersion(CfgItem...这种重复工作显然可以抽象一个更加方便 API 类型出来,希望能更轻松进行使用。...(key); // 1 ... } 这样简单多了,Get 函数调用者可以获知对应 key 类型。...不过,这种形式实现有个小缺点,这里 Db 类型约束非常不明确,对于使用者而言,可能碰到非常难读编译错误,这可能是许多人害怕模板另一个原因。

2K20

C++ 特性使用建议

但是缺省参数函数调用代码难以呈现所有参数,开发者只能通过查看函数申明或定义确定如何使用API,当缺省参数不适用于新代码时可能导致重大问题。...使用异常也带来很多问题,注意以下几点: (1)在现有函数中添加 throw 语句时,必须检查所有调用点,要么让所有调用点统统具备最低限度异常安全保证,要么眼睁睁看异常一路欢快地往上跑,最终中断掉整个程序...编译器可以更好进行类型检测,相应,也能生成更好代码。人们对编写正确代码更加自信,因为他们知道所调用函数被限定了能或不能修改变量值。即使是在无锁多线程编程中,人们也知道什么样函数是安全。...(2)模板编程经常会导致编译出错信息非常不友好:在代码出错时候,即使这个接口非常简单模板内部复杂实现细节也会在出错信息显示。导致这个编译出错信息看起来非常难以理解。...如果你使用递归模板实例化,或者类型列表,或者元函数,又或者表达式模板,或者依赖SFINAE,或者sizeof trick 手段检查函数是否重载,那么这说明你模板太多了,这些模板太复杂了,我们不推荐使用

1.6K20

【CMU15-445 FALL 2022】Project #1 - Buffer Pool

是一个模板元编程工具,用于在编译时根据条件选择是否启用或禁用特定函数模板。...它可以与函数模板、类模板模板别名一起使用。 enable_if通过在函数模板返回类型中使用模板参数作为条件工作。...当条件为true时,返回类型有效并启用函数模板; 当条件为false时,enable_if导致编译器选择其他重载或者删除该函数模板。...); // 调用第二个printNumber模板 printNumber("Hello"); // 错误,没有匹配模板可用 return 0; } 在上面的示例中,我们定义了两个重载函数模板...enable if 适用于需要在模板函数中根据类型或条件启用或禁用特定实例化情况。它通常用于模板函数重载模板参数限制。

25530

Visual C++ 中重大更改

这些无效实例化通常不会导致编译器错误,这被称为 SFINAE(替换失败不是错误)原则。 现在,如果 SFINAE 要求编译器将类模板专用化进行实例化,则在此过程中发生任何错误都是编译器错误。...在这种情况下,解决方法是在定义类之前,不使用此类类型特征。 如果将 D 和 B 定义移到代码文件开头,错误将得到解决。... 定义了其余重载,因此为了获取所有重载,其中一个需要包括 标头。 这就会导致只包括 代码中函数重载解析出现问题。...这些更改不会导致编译时错误,但可能根据标准使程序以不同方式更准确运行。 ...在早期版本库中,此函数签名为:             wchar_t* wcstok(wchar_t*, wchar_t const*)             它使用内部每个线程上下文跟踪跨状态调用

5.1K10

每个C++开发者都应该学习和使用C++11特性

这种方式存在一些问题,比如: 在重载函数或者模板中,如果同时存在参数为指针类型和整数类型函数,传递 NULL 或 0 可能导致调用了错误重载版本。...安全性:在重载函数或者模板中,使用 nullptr 可以避免因为整数类型隐式转换导致调用错误重载版本问题。 语法清晰:使用 nullptr 可以让代码更加清晰明了,表达程序员意图。...总的来说,nullptr 是 C++11 引入一个有益改进,它能够提高代码可读性和安全性,并且在模板编程和重载函数等场景下尤为有用。因此,建议在新代码中使用 nullptr 表示空指针。...这种语法形式简洁清晰,避免了传统for循环中需要显式使用迭代器或索引繁琐。...对于大型对象或对象包含动态分配资源,这种复制操作可能导致昂贵性能开销,尤其是在函数参数传递和返回值返回时。 2.

5210

Visual C++ 中重大更改

这些无效实例化通常不会导致编译器错误,这被称为 SFINAE(替换失败不是错误)原则。 现在,如果 SFINAE 要求编译器将类模板专用化进行实例化,则在此过程中发生任何错误都是编译器错误。...在这种情况下,解决方法是在定义类之前,不使用此类类型特征。 如果将 D 和 B 定义移到代码文件开头,错误将得到解决。... 定义了其余重载,因此为了获取所有重载,其中一个需要包括 标头。 这就会导致只包括 代码中函数重载解析出现问题。...这些更改不会导致编译时错误,但可能根据标准使程序以不同方式更准确运行。 ...在早期版本库中,此函数签名为:             wchar_t* wcstok(wchar_t*, wchar_t const*)             它使用内部每个线程上下文跟踪跨状态调用

4.7K00

C++特性使用建议

但是缺省参数函数调用代码难以呈现所有参数,开发者只能通过查看函数申明或定义确定如何使用API,当缺省参数不适用于新代码时可能导致重大问题。...万不得已使用异常时要注意以下几点: (1)在现有函数中添加 throw 语句时,必须检查所有调用点,要么让所有调用点统统具备最低限度异常安全保证,要么眼睁睁看异常一路欢快地往上跑,最终中断掉整个程序...编译器可以更好进行类型检测,相应,也能生成更好代码。人们对编写正确代码更加自信,因为他们知道所调用函数被限定了能或不能修改变量值。即使是在无锁多线程编程中,人们也知道什么样函数是安全。...(2)模板编程经常会导致编译出错信息非常不友好:在代码出错时候,即使这个接口非常简单模板内部复杂实现细节也会在出错信息显示。导致这个编译出错信息看起来非常难以理解。...如果你使用递归模板实例化,或者类型列表,或者元函数,又或者表达式模板,或者依赖SFINAE,或者sizeof trick 手段检查函数是否重载,那么这说明你模板太多了,这些模板太复杂了,我们不推荐使用

1.9K30
领券