这是来自:https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/include/std/type_traits
template<typename _Xp, typename _Yp>
using __cond_res
= decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()());
...
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1, _Tp2, 3,
void_t<__cond_res<_Tp1, _Tp2>>>
{ using type = __cond_res<_Tp1, _Tp2>; };
我试图弄清楚_Xp(&)()
是什么--它是一个函数调用签名吗?即构造器?这说不通啊这里似乎有一个匿名变量名,即:
_Xp(&anon)()
我仍然无法理解它,在过去的34年里,我一直在编写C++。
任何解释都是赞赏的。谢谢
3条答案
按热度按时间qqrboqgw1#
tl;dr;我们需要一种方法来生成一个类型和值类别为
T
的表达式,而不是类型和值类别为T&&
的表达式,所以我们不能只使用std::declval<T>()
,而是需要做一些其他的事情。重点是
给予
false ? x : y
的类型,其中x
是类型和值类别_Xp
的表达式,y
是类型和值类别_Yp
的表达式。条件运算符(通常称为三元运算符)
?:
是一个非常复杂的语言特性。这是语言中的一个地方,实际上在纯右值和x值之间存在区别。实现这一点的简单方法是:
因为,好吧,这不就是
declval<T>()
的作用吗,给予你一个T
?但实际上,这里有一个缺陷,因为declval
没有指定为:它被指定为(
add_rvalue_reference_t<T>
而不是T&&
,以正确处理void
):因此,
__cond_res<int, int>
和__cond_res<int&&, int&&>
将无法区分,即使第一个需要是int
,而后者需要是int&&
。因此,我们需要一种方法来实际生成
T
类型的任意表达式。一种方法就是:这个管用
另一种方法是生成一个函数的示例,它提供
T
,然后调用它。这就是declval<_Xp(&)()>()()
所做的--给你一个返回_Xp
的空值函数的引用,然后调用它,给你一个_Xp
(正确的值类别)。在这种情况下,与
better_declval
方法相比,这似乎是不必要的复杂性,但事实证明,这种模式在其他上下文中也很有用。相似概念:这里,我有一个概念,检查是否可以用
T
类型的表达式调用f
,包括正确区分纯右值和xvalues。以上是我所知道的实现这一目标的最简单的方法。当然,这很不幸。您还可以:
我想这取决于你的观点,以及你需要使用
obj
多少次。一旦您在概念上下文中看到了这个
T(&)()
模式,它就是一个熟悉的模式,因此一致地使用它是有意义的。wgxvkvu92#
declval<_Xp(&)()>()-这是什么意思
_Xp(&)()
是对不带参数的函数的引用。declval<_Xp(&)()>()
(意思是std::decvlval
)是这个函数的一个假设示例。declval<_Xp(&)()>()()
正在调用那个假设的示例,并产生一个返回值。总的来说,它的意思是“通过调用
_Xp
类型的函数返回的值”。kq4fsx7k3#
_Xp(&)()
是对一个不带参数并返回_Xp
的函数的引用。declval<_Xp(&)()>()()
返回这样的函数引用并调用它,结果是_Xp
。...是
_Xp
和_Yp
的常见类型,遵循条件运算符的规则。与只使用
declval<_Xp>()
的区别在于,declval
不返回值,而是返回std::add_rvalue_reference_t<_Xp>
。您可以看到,此类型别名用于确定两个类型之间的公共引用: