`decltype(true ? std::declval<T1>() : std::declval<T2>())` 是如何工作的?

问题描述 投票:0回答:1

我看到了模板函数 max 的示例代码。

template <typename T1,
          typename T2,
          typename RT = std::decay_t<decltype(true ? std::declval<T1>()
                                                   : std::declval<T2>())>>
RT max (T1 a, T2 b) {
    return b < a ? a : b;
}

我知道什么是

decltype
declval
。但我不明白为什么它使用总是 true 的三元运算符来推断返回类型。

如果我使用

max(1, 2.5)
,它会返回
double
类型的
2.5
,这意味着
RT
被推导为第二个参数
T2
double
。即使
decltype
仅返回
T1
的类型,怎么可能?

(我知道我可以使用

auto
作为返回类型来简化代码。但我的目的是了解奇怪代码的用法。)

c++ templates decltype declval
1个回答
0
投票

decltype(true ? std::declval<T1>() : std::declval<T2>())
是一个穷人试图获得
T1
T2
的“普通类型”。据推测,如果
T1 = int
T2 = double
,则应为
double
,因为
int
在诸如
double
之类的表达式中将转换为
int{...} + double{...}

参见 '?:'(三元/条件运算符)的结果类型是什么?

我说poor-man's是因为

std::declval
返回一个右值引用,所以
RT
将是一个右值引用,而这个函数模板基本上无法使用。您可以按如下方式验证:

template int&& max(int, int); // explicit instantiation

这会产生以下编译器错误(https://godbolt.org/z/3dWzvh9v3):

<source>:8:12: error: rvalue reference to type 'int' cannot bind to lvalue of type 'int'
    8 |     return b < a ? a : b;
      |            ^~~~~~~~~~~~~
<source>:11:16: note: in instantiation of function template specialization 'max<int, int, int &&>' requested here
   11 | template int&& max(int, int);
      | 

更好的定义是:

template <typename T, typename U, typename R = std::common_type_t<T, U>>
R max(T a, U b) {
    return b < a ? a : b;
}

或者:

// C++20 abbreviated function template
// C++11 trailing return type with decltype
auto max(auto a, auto b) -> decltype(b < a ? a : b) {
    return b < a ? a : b;
}
© www.soinside.com 2019 - 2024. All rights reserved.