gpt4 book ai didi

c++ - 为什么 enable_if<>* = nullptr 有效而 enable_if<> = void 无效?

转载 作者:太空狗 更新时间:2023-10-29 21:09:46 25 4
gpt4 key购买 nike

基本问题陈述

我正在学习 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;
}

编译器提示 foo是多重定义的。互联网告诉我这是因为在检查函数签名时模板参数不相关。

我尝试过的变体

为了尽可能进行最基本的元编程,我开始使用语法来解决这个问题。这是我为 enable_if 尝试过的事情列表语句(反向语句即 !std::is_base_of 相同,但为简洁起见省略):

匿名类型,编号 typename , 等于 0

https://en.cppreference.com/w/cpp/types/enable_if告诉我我上面做的是错误的。但它的建议(在第一个注释 block 下找到)是适当的隐秘,更重要的是,也不能编译。

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 = ... ),它无法编译。

如果有人更熟悉 TMP 和 enable_if,我将不胜感激会向我解释:

  1. 为什么要声明 enable_if作为指向类型的指针并将其默认为 nullptr工作?
  2. 默认enable_if的语义规则是什么? ?
  3. enable_if 产生的命名类型的语义规则是什么? ?
  4. 是否有我可以使用的引用资料,它清楚地解释了这个规则以及模板领域中的其他类似规则?

非常感谢。

最佳答案

您只是设置模板类型参数值的第一组变体。两个具有不同模板类型参数值的重载发生冲突,因为它们都是同类 template<class,class>并具有相同的函数参数。

非类型模板参数情况,如果您最终拥有类型为 void 的模板非类型参数,则使用原始启用的情况。那是非法的;各种错误消息是非法的各种方式。

当你添加一个星号,当enable if子句通过时,它是一个类型为void指针的模板非类型参数。

当它失败时,它根本就不是一个参数。

与 nullptr 情况等价的是:

std::enable_if_t<std::is_base_of_v<Base, T>, bool> = true

当子句为真时,enable if 的计算结果为 bool ,我们得到:

bool = true

默认为 true 的 bool 类型的模板非类型参数。当子句(子句的基础)为假时,我们得到 SFINAE 失败;那里没有模板类型或非类型参数。


随着 class Whatever = enable_if我们基于模板参数的默认值尝试 SFINAE 的情况。这会导致签名冲突,因为如果在重载解析期间(在同一阶段)找到签名,则签名必须是唯一的。

随着 enable = value在某些情况下,我们正在尝试基于 如果 存在模板非类型参数的 SFINAE。失败时,没有可供比较的签名,因此不会发生冲突。

剩下的就是让语法简单漂亮。

现在,这在概念画板中已经过时了,所以不要迷恋语法。

关于c++ - 为什么 enable_if<>* = nullptr 有效而 enable_if<> = void 无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57339923/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com