【问题标题】:C++ Templates - The Complete Guide: Wording of footnote about decltype and return typeC++ 模板 - 完整指南:关于 decltype 和返回类型的脚注措辞
【发布时间】:2021-11-19 23:03:50
【问题描述】:

C++ 模板 - 完整指南第 2 版在第 436 页有以下脚注(我的粗体):

除了 decltype(<i>call-expression</i>) 不需要非引用、非void 返回类型是完整的,这与其他上下文中的调用表达式不同。改用decltype(std::declval&lt;T&gt;().begin(), 0) 确实增加了调用的返回类型是完整的要求,因为返回的值不再是decltype 操作数的结果

脚注指的是使用decltype(std::declval&lt;T&gt;().begin())(无效,基于脚注)来测试在T 上调用.begin() 是否有效。使用它的代码如下(为了清楚起见,它周围有一些文本:

诀窍是制定表达式来检查我们是否可以在 decltype 表达式中调用 begin() 以获得附加函数模板参数的默认值:

#include <utility>      // for declval
#include <type_traits>  // for true_type, false_type, and void_t
// primary template:
template<typename, typename = std::void_t<>>
struct HasBeginT : std::false_type {};
// partial specialization (may be SFINAE’d away):
template<typename T>
struct HasBeginT<T, std::void_t<decltype(std::declval<T>().begin())>>
  : std::true_type {
};

在这里,我们使用decltype(std::declval&lt;T&gt;().begin()) 来测试给定T 类型的值/对象(使用std::declval 以避免需要任何构造函数),调用成员begin() 是否有效。

this previous question of mine了解到,既然operator,可以被重载,那么, 0的作用就是触发否则不存在的重载解析,而这又需要std::declval&lt;T&gt;().begin()的类型是完整的.

但是,书中的文字(参见上面粗体突出显示的部分)没有提到operator,,也没有提到重载决议。这只是糟糕的措辞吗?或者也许只是从不同的角度看待同一件事?还是什么?

【问题讨论】:

  • begin() 意味着要返回一个迭代器,并且迭代器具有相当熟悉的预期 API,因此对于该示例,假设不会有重载的逗号运算符是模糊合理的。不过,在一般情况下,您的观点是合理的。
  • HolyBlackCat 解释了我在评论 cigien 的答案时的心态。但我会修改它。类型不必仅仅因为重载就完整。显然,对于函数调用(例如重载),参数必须是完整的(初始化和反初始化是调用的一部分)。但即使在没有重载的情况下,逗号运算符也会评估并丢弃 lhs。对于类纯右值,这涉及到实现一个临时值,因此我们再次进行初始化和反初始化,并需要一个完整的类型。
  • 我认为您误解了原始源材料在说什么,但我不能确定,因为您只添加了一个脚注,我不知道它在说什么。 “在 T 上调用 begin() 是有价值的”在 C++ 中的含义是模糊的,有多种合理的方法可以将英语中的“有效”一词映射到 C++ 中的不同概念。我不知道decltype在哪里,也不知道目标是什么。
  • @Yakk-AdamNevraumont,我是否添加了足够的信息?

标签: c++ templates c++17 decltype comma-operator


【解决方案1】:

作者似乎忘记或忽略了, 被超载的可能性。整个技术在这方面存在缺陷,不仅仅是措辞。

因此,如果begin() 有效并返回完整类型,但, 已重载且由于某种原因无法调用,则会得到假阴性。

更强大的解决方案是decltype(void(std::declval&lt;T&gt;().begin()))

【讨论】:

  • 如果我说的正确(在这种情况下)void(std::declval&lt;T&gt;().begin())(void)std::declval&lt;T&gt;().begin() 相同,这意味着您将.begin() 的结果转换为void.. 。 这是如何运作的?为什么它具有强制执行该要求的效果?
  • @Enlico 你没有正确地问这个问题IMO。您的问题集中在书中的措辞上,而根据您所有的 cmets,您应该询问 decltype 的行为以及涉及不完整类型的子表达式。
  • @cigien 这是另一个问题。但现在我不知道该怎么问。我基本上会链接您链接的页面并要求向我解释这一点
  • @Enlico 够公平的。我会看看我是否可以自己提出这个问题,如果可以的话,我会发布一个。
猜你喜欢
  • 1970-01-01
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多