C++ std::enable_if解析
来源:互联网 发布:rx100 m3 m4 m5知乎 编辑:程序博客网 时间:2024/06/05 16:18
引言
今日在阅读LLVM相关源码时(如下所示),遇到了enable_if<>这个概念,以前从没有遇到过,这里做个小记。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
enable_if 的主要作用就是当某个 condition 成立时,enable_if可以提供某种类型。enable_if在标准库中通过结构体模板实现的,声明如下:
- 1
- 1
英文解释如下:
Enable type if the condition is met.
The type T is enabled as member type enable_if::type if Cond is true. Otherwise, enable_if::type is not defined.
但是当 condition 不满足的时候,enable_if<>::type 就是未定义的,当用到模板相关的场景时,只会 instantiate fail,并不会编译错误,这时很重要的一点。为了理解 std::enable_if<> 的实现,我们先来了解一下 SFINAE。
SFINAE
SFINAE 是C++ 的一种语言属性,具体内容就是”从一组重载函数中删除模板实例化无效的函数”。
Prune functions that do not yield valid template instantiations from a set of overload functions.
SFINAE 的的全称是 Substitution Failure Is Not An Error。
SFINAE 应用最为广泛的场景是C++中的 std::enable_if,这里有完整的英文描述:
In the process of template argument deduction, a C++ compiler attempts to instantiate signatures of a number of candidate overloaded functions to make sure that exactly one overloaded function is available as a perfect match for a given function call.
从上面的描述中我们可以看到,在对一个函数调用进行模板推导时,编译器会尝试推导所有的候选函数(重载函数,模板,但是普通函数的优先级要高),以确保得到一个最完美的匹配。
If an invalid argument or return type is formed during the instantiation of a function template, the instantiation is removed from the overload resolution set instead of causing a compilation error.
As long as there is one and only one function to which the call can be dispatched, the compiler issues no errors.
也就是说在推导的过程中,如果出现了无效的模板参数,则会将该候选函数从重载决议集合中删除,只要最终得到了一个 perfect match ,编译就不会报错。
如下代码所示:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
main 函数调用 multiply 会使编译器会尽可能去匹配所有候选函数,虽然第一个 multiply 函数明显是较优的匹配,但是为了得到一个最精确的匹配,编译器依然会尝试去匹配剩下的候选函数,此时就会去推导 第二个multiply函数,中间在参数推导的过程中出现了一个无效的类型 int::multiplication_result ,但是因为 SFINAE 原则并不会报错。
std::enable_if<> 的实现
前面我们在介绍 std::enable_if 的时候提到,如果 condition 不满足的话,会生成一个无效的类型,此处由于SFINAE 机制的存在,只要 call 存在一个匹配的话,就不会报错(只是简单的丢弃该函数)。
std::enable_if<>的实现机制如下代码所示:
- 1
- 2
- 3
- 1
- 2
- 3
从上面的代码可以看到
在 condition 为真的时候,由于偏特化机制,第二个结构体模板明显是一个更好的匹配,所以 std::enable_if<>::type 就是有效的。
当 condition 为假的时候,只有第一个结构体模板能够匹配,所以std::enable_if<>::type 是无效的,会被丢弃,编译器会报错:error: no type named ‘type’ in ‘struct std::enable_if<false, bool>。
Note: 下面是Visual Studio 2013的实现:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
std::enable_if<> 使用及使用
std::enable_if<> 的使用原型如下所示:
- 1
- 1
- Cond, A compile-time constant of type bool
- T, A type.
使用 enable_if 的时候,对参数有这两方面的限制。
该例子来自于 这里:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- C++ std::enable_if解析
- C++ std::enable_if解析
- enable_if
- enable_if
- enable_if
- enable_if
- C++~~~std::sort
- 【C++】std::copy
- C++-----------------------------------------------------std::bind
- C++:线程(std::thread)
- c++STD库函数收集
- C++-std::Vector
- [STL]源码解析:std::vector
- boost学习之-enable_if
- boost::enable_if 详解
- boost.core.enable_if
- c++11之enable_if
- enable_if 源码剖析
- Python中作用域
- 绑定Service bindService
- Linux运维笔记-文档总结-openssh-server
- Intellij 新建文件 自动add进版本控制SVN 或 GIT
- 两个html页面之间的传值
- C++ std::enable_if解析
- Android 积累一些JNI与NDK的知识
- sudo的环境变量获取
- 百度地图初见
- ajax请求如何避免表单重复提交
- 解决导入ReactiveCocoa框架报错问题
- 两个栈实现一个队列/两个队列实现一个栈
- POJ 3273 (最大组最小值)
- POJ 1269