14 | SFINAE:不是错误的替换失败是怎么回事?
该思维导图由 AI 生成,仅供参考
函数模板的重载决议
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了C++模板编程中的SFINAE(Substitution Failure Is Not An Error)概念及其应用。文章首先讨论了函数模板的重载决议过程,并介绍了SFINAE的最初用法。随后详细讨论了SFINAE在编译期成员检测中的应用,包括使用enable_if模板和has_reserve模板来选择性地启用函数重载,以及利用decltype返回值和void_t模板来避免错误的重载。通过这些技巧,读者可以在C++模板编程中灵活地进行类型检测和函数重载的控制。文章内容涵盖了C++模板编程中的高级技术,对于想要深入了解模板元编程的读者具有很高的参考价值。 总结:本文深入介绍了C++模板编程中SFINAE的概念及其应用,包括函数模板的重载决议过程和SFINAE在编译期成员检测中的灵活应用。通过学习本文内容,读者可以掌握在C++模板编程中灵活进行类型检测和函数重载控制的技巧。
《现代 C++ 编程实战》,新⼈⾸单¥59
全部留言(29)
- 最新
- 精选
- 三味emmmm.... 这一节内容如果是半年前看到,应该能节省我好多时间去写序列化,真是我实实在在的需求啊! 我自己在写数据序列化为json文本的时候,就遇到了这样头疼的问题:如何根据类型,去调用对应的函数。 如果是简单的int,bool,float,直接特化就好了。 如果是自定义的结构体呢?我的做法就是判断自定义结构体中是否有serializable和deserializable函数,就用到了文中最开始的方法判断。 然而那会儿我写得还是太简单粗暴,在代码中用的是if去判断,对于不支持的类型,直接报错,并不能做到忽略。 看了本文之后,真是受益颇多啊!留言于此,告诉大家,别以为用不到这些内容,都是实实在在的干货!
作者回复: 我喜欢这样的留言。哈哈,写专栏就是希望能给大家帮助的。😇
2019-12-3034 - 禾桃请问有编译器本身什么工具或者日志模式,可以显示模版实例化的过程?
作者回复: 新发现一个工具,可以展示实例化的过程。你可以去看一下: https://cppinsights.io/
2019-12-27216 - 好好虚度时光表示真的太烧脑了
作者回复: 这个网站也许可以帮你: https://cppinsights.io/
2020-01-1726 - _呱太_刚更新的时候看得头晕目眩,发现基础不够。回头抽空撸完了 STL 标准库 和 effective modern C++,回过头来看豁然开朗,真实受益匪浅
作者回复: 欢迎走上一个台阶。学习无止境……
2020-04-095 - 西加加看完了两课之后,正儿八经的想把各种 type_traits 用起来了。
作者回复: 在合适的地方使用,记住目标是简化最终代码就行。模板代码容易让人脑袋疼是事实,限制主要用在底层的支持代码里。上层的使用代码一定要简单为好。
2020-05-163 - 常振华标签分发那里的: template void append(C& container, T* ptr, size_t size) { _append( container, ptr, size, integral_constant< bool, has_reserve<C>::value>{});} 这个integral_constant< bool, has_reserve<C>::value>{}看不明白 integral_constant是上一讲的 template <class T, T v> struct integral_constant { static const T value = v; typedef T value_type; typedef integral_constant type; }; 吧? has_reserve<C>::value的::value是啥意思?
作者回复: 看看下面的例子,是不是可以了? integral_constant<int, 1>::value == 1 integral_constant<int, 2>::value == 2 true_type::value == integral_constant<bool, true>::value == true
2021-10-132 - geek老师, template <typename T, typename = void_t<>> struct has_reserve : false_type {}; template <typename T> struct has_reserve< T, void_t<decltype( declval<T&>().reserve(1U))>> : true_type {}; 第二个是一个类特化,但我理解,第二个中void的模板参数的推导结果和第一个是一样的。那此处 更特殊 这个意思是体现在 void的模板参数推导过程(无错)吗?
作者回复: 不是所有类型都能满足第二个模板。
2021-03-082 - Simontypename = void_t<> 这个写法是什么意思?类型名是不重要的?
作者回复: 等效于 typename = void。类型参数名不重要。这样,特化的版本和通用的版本,后一项都是 void,不用调用者提供。 通用模板形式的第二个参数如果不是 void,那特化形式就永远不能匹配成功了,除非调用者手工提供第二项 void(第二项 void_t 的结果仍是 void)。
2022-08-01归属地:广东1 - 李亮亮template <typename T, typename = void_t<>> struct has_reserve : false_type {}; 这里的冒号是什么语法?
作者回复: 继承啊。
2019-12-3021 - 。用 void_t 实现的 has_reserve 函数有一些问题,它没法判断类型的reserve 方法的返回值是否是 void,所以可以修改一下: template <typename T, typename = void> struct has_reserve : std::false_type {}; template <typename T> struct has_reserve<T, std::__void_t<decltype(std::declval<T&>().reserve(1U))>> : std::is_void<decltype(std::declval<T&>().reserve(1U))> {};
作者回复: 看你关心什么了。我不关心/要求 reserve 没有返回值。 另外,不要使用 __void_t。这不是标准的一部分(是某些编译器私用的)。
2024-03-10归属地:北京