c++ - 不确定 enable_if 是如何使用的以及为什么它很重要
问题描述
在阅读了一些网站之后,我认为enable_if
如果条件为真,我们可以启用或限制类型?我不太确定,有人可以澄清它到底是什么吗?我也不确定它是如何使用的,以及它在哪些场景中可能是相关的。我还看到了可以使用它的模板参数的各种方式,这让我更加困惑。有多少种方式可以使用?
例如,以下是否意味着bool
如果类型T
为,则返回类型应为int
?
typename std::enable_if<std::is_integral<T>::value,bool>::type
is_odd (T i) {return bool(i%2);}
解决方案
要理解这一点,我们必须深入研究 SFINAE 或“替换失败不是错误”。这是一个有点难以掌握的原则,也是许多编译时模板技巧的核心。
让我们举一个非常简单的例子:
#include <iostream>
struct Bla {
template <typename T,
std::enable_if_t<std::is_integral<T>::value, int> = 0
>
static void klaf(T t)
{
std::cout << "int" << std::endl;
}
template <typename T,
std::enable_if_t<std::is_floating_point<T>::value, int> = 0
>
static void klaf(T t)
{
std::cout << "float" << std::endl;
}
};
int main()
{
Bla::klaf(65);
Bla::klaf(17.5);
}
印刷:
int
float
现在,这是如何工作的?好吧,在Bla::klaf(65)
编译器找到两个匹配名称的函数的情况下,一旦名称查找结束,它会尝试通过替换类型来选择最好的一个(重要提示:名称查找首先发生并且只发生一次,然后是替换。)
取而代之的是(第二个第一个,因为它更有趣):
template <typename T, std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
static void klaf(T t) {...}
-> T becomes int
template <int, std::enable_if_t<std::is_floating_point<int>::value, int> = 0>
static void klaf(int t) {...}
-> is_floating_point<int>::value evaluates to false
template <int, std::enable_if_t<false, int> = 0>
static void klaf(int t) {...}
-> enable_if_t<false,... evaluates to nothing
template <int, = 0>
static void klaf(int t) {...}
-> the code is malformed: ", = 0" does not make sense.
在普通代码中,这将是一个编译错误,但这是模板和“替换失败不是错误”。换句话说; 如果有东西替代了有效代码,编译器会很高兴,忘记所有没有的东西。
嘿,另一个Bla::klaf
选项实际上确实替代了有效代码:
template <typename T, std::enable_if_t<std::is_integral<T>::value, int> = 0>
static void klaf(T t)
-> T becomes int
template <int, std::enable_if_t<std::is_integral<int>::value, int> = 0>
static void klaf(int t)
-> is_integral<int>::value evaluates to true
template <int, std::enable_if_t<true, int> = 0>
static void klaf(int t)
-> enable_if_t<true, int> evaluates to int
template <int, int = 0>
static void klaf(int t)
-> This is actually valid code that the compiler can swallow.
推荐阅读
- asp.net - Entity Framework Core 禁用递归检索 .Include() 函数中的信息
- android - react-native-google-places-autocomplete 不适用于 React native 0.61
- ajax - 在发送 ajax 调用之后调用一个函数
- c - 找到调用我的系统调用的当前进程的 pwd 变量
- android - Android avd 模拟器 - 如何保存“您想保存当前状态以供下次快速启动吗?” 在 config.ini 文件中
- c# - Aspose 不能写多个段落
- spfx - 如何在单个 spfx 解决方案中创建两个 webpart?
- reactjs - 使用 React Hook 与其他组件共享 API 数据,NO REDUX
- ruby-on-rails - 用于捕获给定字符串的特定值的 ruby 正则表达式可以是什么?
- python - 是否有一个函数可以找到忽略峰值的曲线斜率?