12

为了看看它是如何工作的,我查看std::common_type了 header 中的 libstdc++ 实现type_traits。我不得不承认我真的不明白它是如何工作的。这里是:

/// 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;
    };

我很了解第一个、第二个和第四个声明是如何工作的。但是,我无法理解第三个声明是如何工作的。有人可以尝试解释这里使用的机制吗?

4

3 回答 3

12

首先,std::declval<T>()产生一个 r 类型的值T。尝试对该值执行任何操作都会失败,因此它只能在未评估的上下文中使用。接下来,三元运算符将其类型推断为两个参数共有的最专门的类型(如果没有这样的类型,则失败)。所以,表达式的类型

true? declval<T0>(): declval<T1>()

T0是and的最专业的常见类型T1。剩下的就是将这个表达式转换为一个类型并确保它不被评估。decltype(expr)就是这样做的。显然,两个参数版本的逻辑牛肉:其他的用于处理极端情况(一个参数)并利用两个参数版本来产生任意类型的通用类型。

于 2012-09-05T21:42:09.090 回答
4

第三个版本使用条件运算符来确定通用类型。它的规则在标准的第 5.16 节中有相当长的描述,所以我不确定我应该在这里复制它们。

简而言之,表达式:

boolean-expression ? second-operand : third-operand

具有第二个和第三个操作数的“通用类型”(如果存在)。然后decltype使用说明符将表达式“转换”为类型说明符。

于 2012-09-05T21:32:56.437 回答
1

长话短说: decltype 使 C++ 编译器为其确定最接近的祖先类型。

三级运算符具有两个可能表达式的最接近祖先的结果静态类型。

例如:

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++ 编译器确定它是什么类型)

于 2012-09-05T21:35:40.987 回答