Dav*_*ien 25 c++ type-traits c++20
这是来自: 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>; };
Run Code Online (Sandbox Code Playgroud)
我想弄清楚什么_Xp(&)()
是 - 它是函数调用签名吗?即构造函数?确实没有意义。那里似乎有一个匿名变量名,即:
_Xp(&anon)()
Run Code Online (Sandbox Code Playgroud)
我仍然无法理解它,而且过去 34 年我一直在编写 C++ 代码。
任何解释表示赞赏。谢谢。
Bar*_*rry 31
太长;博士;我们需要一种方法来生成具有类型和值类别的表达式T
,而不是类型和值类别T&&
,因此我们不能只是使用std::declval<T>()
,而是需要做其他事情。
这一点的要点是:
template<typename _Xp, typename _Yp>
using __cond_res
= decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()());
Run Code Online (Sandbox Code Playgroud)
是给你类型,false ? x : y
其中x
是类型和值类别的表达式_Xp
,y
是类型和值类别的表达式_Yp
。
条件运算符(通常称为三元运算符)?:
是一个极其复杂的语言特性。这是该语言中实际上区分纯右值和 xvalue 的地方之一。
实现这一点的简单方法是:
template<typename _Xp, typename _Yp>
using __cond_res
= decltype(false ? declval<_Xp>() : declval<_Yp>());
Run Code Online (Sandbox Code Playgroud)
因为,好吧,这不就是declval<T>()
给你一个 吗T
?但实际上,这里有一个缺陷,因为declval
没有指定为:
template <typename T>
auto declval() -> T;
Run Code Online (Sandbox Code Playgroud)
它被指定为(add_rvalue_reference_t<T>
而不是T&&
正确处理void
):
template <typename T>
auto declval() -> std::add_rvalue_reference_t<T>;
Run Code Online (Sandbox Code Playgroud)
结果,__cond_res<int, int>
和__cond_res<int&&, int&&>
是无法区分的,尽管第一个需要是int
,而后者需要是int&&
。
因此,我们需要一种方法来实际生成类型的任意表达式T
。一种方法实际上是:
template <typename T>
auto better_declval() -> T;
template<typename _Xp, typename _Yp>
using __cond_res
= decltype(false ? better_declval<_Xp>() : better_declval<_Yp>());
Run Code Online (Sandbox Code Playgroud)
这有效。
另一种方法是生成一个函数实例T
,然后调用它。这就是declval<_Xp(&)()>()()
- 为您提供对返回 a 的空函数的引用_Xp
,然后调用它,为您提供 an _Xp
(正确的值类别)。
在这种情况下,与该方法相比,这似乎是不必要的复杂性better_declval
,但事实证明,这种模式在其他上下文中也很有用。喜欢的概念:
template <typename T>
concept something = requires (T(&obj)()){
f(obj());
};
Run Code Online (Sandbox Code Playgroud)
在这里,我有一个概念,检查是否可以f
使用 类型的表达式进行调用T
,包括正确区分纯右值和 xvalues。以上是我所知道的实现该目标的最便捷方法。诚然,这是不幸的。
你还可以这样做:
template <typename T>
concept something = requires {
f(better_declval<T>());
};
Run Code Online (Sandbox Code Playgroud)
我想这仅取决于您的观点,以及您需要使用多少次obj
。
一旦您在概念上下文中看到了此T(&)()
模式的使用,就会发现它是一种熟悉的模式,因此一致地使用它是有意义的。
Dre*_*ann 12
declval<_Xp(&)()>()() - 这是什么意思
_Xp(&)()
是对不带参数的函数的引用。
declval<_Xp(&)()>()
(含义std::decvlval
)是该函数的假设实例。
declval<_Xp(&)()>()()
正在调用该假设的实例,产生一个返回值。
总的来说,它的意思是“通过调用 类型的函数返回的值_Xp
”。
_Xp(&)()
是对不带参数并返回 的函数的引用_Xp
。declval<_Xp(&)()>()()
返回这样的函数引用并调用它,这会导致_Xp
.decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()())
Run Code Online (Sandbox Code Playgroud)
_Xp
... 是and的常见类型_Yp
,遵循条件运算符的规则。
与仅使用的区别declval<_Xp>()
在于,declval
它不返回值,而是返回std::add_rvalue_reference_t<_Xp>
。
您可以看到此类型别名用于确定两种类型之间的公共引用:
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1, _Tp2, 3, void_t<__cond_res<_Tp1, _Tp2>>>
{ using type = __cond_res<_Tp1, _Tp2>; };
Run Code Online (Sandbox Code Playgroud)
注意:您可以使用cdecl+来更好地理解 C 和 C++ 类型语法。
归档时间: |
|
查看次数: |
1390 次 |
最近记录: |