template <typename I, typename D>
auto suma(I i, D d) -> decltype(i + d)
{
return i + d;
}
template <typename I, typename D, typename ... T>
auto super_suma(I i, D d, T ... tipos)
{
???? sub_suma = suma(i, d);
// ~~~~ <--- que tipo debo usar aqui?
if constexpr (sizeof...(tipos) >= 2)
return sub_suma + super_suma(tipos ...);
if constexpr (sizeof...(tipos) == 1)
return sub_suma + std::get<0>(std::make_tuple(tipos ...));
if constexpr (sizeof...(tipos) == 0)
return sub_suma;
}
sub_suma在函数变量中super_suma返回静态类型推导(auto)来救援:
template <typename I, typename D, typename ... T>
auto super_suma(I i, D d, T ... tipos)
{
auto sub_suma = suma(i, d);
// ~~~~ <--- Deja que el compilador lo deduzca por ti!
if constexpr (sizeof...(tipos) >= 2)
return sub_suma + super_suma(tipos ...);
if constexpr (sizeof...(tipos) == 1)
return sub_suma + std::get<0>(std::make_tuple(tipos ...));
if constexpr (sizeof...(tipos) == 0)
return sub_suma;
}
auto
允许您从变量开始的值推断类型:但是,
auto
它无法涵盖所有可能性……想象一下,您必须编写一个模板,这样:
您如何对该模板进行编程?
版本 1
在 C++17 中有效,在 C++11 中无效
第 2 版
与所有版本兼容,但使用起来有点麻烦,因为虽然
U
可以自动推断类型,但T
必须明确指出类型:2.1版
为了推导出这两个值,我们创建了一个中间结构作为特征:
尽管很容易理解,这种解决方案开始变得相当繁琐。
第 3 版
...或者我们也可以使用
decltype
在这种情况下,它
decltype
计算的表达式T().otraFunc()
只不过是:T()
:模拟创建类型的新对象T
T().otraFunc()
模拟调用并为该类型保留函数的返回otraFunc
类型T
可能会发生默认构造函数
T
不适用于给定类型...在这种情况下无法评估上述表达式...我们可以使用指针获得更通用的版本:由于
decltype
它不执行代码而只是对其进行评估,因此不存在内存泄漏或调用无效对象的风险......当然我们不能使用new
......顺便说一句,有些人更喜欢 C++11 中其他完全有效的命名法
当然
decltype
它也可以用来评估更简单的表达式:编辑
另一种使用方式
decltype
,与declval
. 所以我们不必担心应该如何创建对象T
:decltype
而且auto
它们不可互换或等效,它们的用途、行为和目的是不同的。auto
是一个声明器,它在可以通过初始化进行声明的地方推断类型:const
orvolatile
限定,则如果应用于对象(第一级限定符),这些限定符将被忽略。decltype(...)
是一个复制已经存在的东西类型的声明器:至于何时使用它们,就像任何工具一样:必要时。
什么时候需要?
auto
没有和的帮助,有些事情是无法编程的decltype
;它们通常是程序员不可能(或很难)知道但对编译器来说微不足道的事情,例如未知类型之间的操作:在模板函数的上下文中,
suma
程序员不可能知道函数的返回类型,我们不知道它是I
什么类型以及它是什么类型,D
直到我们实例化模板时我们才会知道,但是我们不能在 ! 编译时更改模板!幸运的是,编译器拥有程序员缺少的信息,并且在实例化模板时知道它们是什么类型,
I
并且D
在这种情况下auto
,它告诉编译器:“我不知道函数的返回类型是什么但稍后会推导出“同时decltype
它会告诉你”推导出表达式的类型i + d
并将其分配给函数的返回值suma
“。以便:
suma(1, 2.f)
有作为返回类型float
。suma<std::string>("patatas", " fritas!")
有作为返回类型std::string
。由于同样的原因导致我们忽略了这个函数的返回类型,我们不能创建一个变量来捕获它的值:
sub_suma
在函数变量中super_suma
返回静态类型推导(auto
)来救援:注意
super_suma
它在定义之后不使用-> decltype
;这是 C++14 的一个特性,称为函数返回类型推导。的限制
auto
和decltype
它的工作方式
auto
使得无法派生引用,除非你明确地这样做:如果我们想隐含地将返回值推断为
const
(这是实际类型),我们应该依赖decltype
:从 C++14 开始,可以使用以下方法组合
decltype
并auto
更直接地推断函数的实际返回类型decltype(auto)
:有时这不是必需的,但它很有用。
声明
auto
器允许我们在通常需要复制它的地方忽略类型,例如:阅读起来比这更舒服:
它还允许我们完全忽略类型,因此:
阅读起来比这更舒服:
这种类型的使用
auto
引起了一种称为“几乎总是auto
”的趋势(英文为“ Almost Always Auto ”或 AAA,由Herb Sutter创造的术语),它建议我们auto
在几乎所有情况下都使用它。专门针对 AAA的文章非常好1,我只会翻译我认为最相关的部分:1虽然我并不完全同意。