ten*_*jed 6 c++ templates enable-if c++17
基本问题陈述
我正在学习 SFINAE。我尝试了一个非常简单的enable_if:
// 1: A foo() that accepts arguments that are derived from Base
template <typename T, typename Enable = enable_if_t<std::is_base_of_v<Base, T>>>
void foo(T thing) {
std::cout << "It's a derived!" << std::endl;
}
// 2: A foo() that accepts all other arguments
template <typename T, typename Enable = enable_if_t<!std::is_base_of_v<Base, T>>>
void foo(T thing) {
std::cout << "It's not a derived." << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨说foo是多重定义的。互联网告诉我,这是因为检查函数签名时模板参数不相关。
我试过的变体
为了尽可能进行最基本的元编程,我开始用语法来解决这个问题。这是我为该enable_if语句尝试的内容列表(倒置语句,即!std::is_base_of相同,但为简洁起见省略了):
匿名类型,否typename,等于0
https://en.cppreference.com/w/cpp/types/enable_if告诉我我上面做的事情是错误的。但是它的建议(在第一个注释块下找到)是适当的神秘,更重要的是,也无法编译。
std::enable_if_t<std::is_base_of_v<Base, T>> = 0
匿名类型,否typename,等于void
考虑到如果我正在使用类型进行编程,使用类型将是一个明智的选择,我反而尝试将模板默认为void. 没有骰子。
std::enable_if_t<std::is_base_of_v<Base, T>> = void
匿名类型,是typename,等于void
当我们在上面抛出语法时,如果我将此模板参数默认为一个类型,我不应该使用 typename 关键字吗?
typename std::enable_if_t<std::is_base_of_v<Base, T>> = void
最后,哦,显然是有效的
typename enable_if_t<std::is_base_of_v<Base, T>, T>* = nullptr
我已经问过每个我知道为什么这有效但我的其他变体却没有的人,他们同样感到困惑。我不知所措。更令人困惑的是,如果我将这种类型命名为(例如typename Enable = ...),它将无法编译。
如果有一位更熟悉 TMPenable_if并向我解释的人,我将不胜感激:
enable_if为指向类型的指针并默认它nullptr起作用?enable_if什么?enable_if什么?非常感谢。
第一组变体只是设置模板类型参数的值。模板类型参数的两个具有不同值的重载会发生冲突,因为它们都是同类template<class,class>并且具有相同的函数参数。
非类型模板参数情况,如果您最终拥有类型为 void 的模板非类型参数,则使用原始启用的情况。那是非法的;各种错误信息是非法的各种方式。
当您添加星号时,当 enable if 子句通过时,它是 void 指针类型的模板非类型参数。
当它失败时,它根本不是一个争论。
相当于 nullptr 的情况是:
std::enable_if_t<std::is_base_of_v<Base, T>, bool> = true
Run Code Online (Sandbox Code Playgroud)
当子句为真时, enable if 计算为bool,我们得到:
bool = true
Run Code Online (Sandbox Code Playgroud)
一个默认为 true 的 bool 类型的模板非类型参数。当子句(子句的基础)为假时,我们得到 SFINAE 失败;那里没有模板类型或非类型参数。
对于这些class Whatever = enable_if案例,我们正在尝试基于模板参数的默认值的 SFINAE。这会导致签名冲突,因为如果在重载解决期间(在同一阶段)找到签名,则签名必须是唯一的。
随着enable = value情况下,我们是基于试图SFINAE如果有一个模板非类型参数存在。失败时,没有要比较的签名,因此不会发生冲突。
剩下的就是让语法简单漂亮。
现在,概念已经过时了,所以不要爱上语法。