为了了解它是如何工作的,我在标题std::common_type
中查看了type_traits
的libstdc ++实现。我不得不承认我并不真正理解它是如何运作的。这是:
/// common_type
template<typename... _Tp>
struct common_type;
template<typename _Tp>
struct common_type<_Tp>
{ typedef _Tp type; };
template<typename _Tp, typename _Up>
struct common_type<_Tp, _Up>
{ typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; };
template<typename _Tp, typename _Up, typename... _Vp>
struct common_type<_Tp, _Up, _Vp...>
{
typedef typename
common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
};
我完全理解第一,第二和第四声明的工作原理。但是,我无法理解第三个声明的工作原理。有人可以尝试解释这里使用的机制吗?
答案 0 :(得分:10)
首先,std::declval<T>()
会产生T
类型的r值。尝试对值执行任何操作都将失败,因此它只能在未评估的上下文中使用。接下来,三元运算符将其类型推断为两个参数共有的最特殊类型(如果没有这样的类型,则失败)。那么,表达式的类型
true? declval<T0>(): declval<T1>()
是T0
和T1
中最专业的常见类型。剩下的就是将这个表达式转换为一个类型并确保它不被评估。 decltype(expr)
就是这样做的。显然,逻辑的两个论证版本:其他的是处理角落案例(一个论证)并利用两个论证版本来产生任意类型的共同类型。
答案 1 :(得分:3)
第三个版本使用条件运算符来确定公共类型。它的规则在标准的第5.16节中有相当长的描述,所以我不确定我应该在这里复制它们。
简单地说,表达式:
boolean-expression ? second-operand : third-operand
有一个&#34;普通类型&#34;第二和第三个操作数,如果存在的话。然后decltype
说明符用于&#34;转换&#34;将表达式转换为类型说明符。
答案 2 :(得分:1)
Long Story Short:decltype使C ++编译器确定最接近它的祖先类型。
第三级算子具有两种可能表达式中最接近祖先的静态类型。
E.g:
A继承自B
X继承自Y继承自B
<expression> ? <expression with static type A> : <expression with static type X>
= <expression with static type B> // this is how the C++ parser sees it
这就是C ++语言的工作原理。 decltype只是使typedef成为该表达式结果的静态类型(C ++编译器决定它的类型)