类型是如何从自动返回类型推导出来的
How is type deduced from auto return type?
这个答案的代码片段如下:
template<class T, class F>
auto f(std::vector<T> v, F fun)
-> decltype( bool( fun(v[0] ) ), void() )
{
// ...
}
它真的可以编译和工作(至少在Ideone上是这样)。
那么,在这种情况下,类型是如何推导出来的呢?
c++11标准真的允许下一行吗?
decltype( bool( fun(v[0] ) ), void() )
我快速看了一眼,但它看起来并不有效。这种情况下ideone错了吗?
c++11标准中的所有例子都是这样的,它们在decltype中只有一个类型:
struct A {
char g();
template<class T> auto f(T t) -> decltype(t + g())
{ return t + g(); }
};
另一个例子:
void f3() {
float x, &r = x;
[=] {
decltype(x) y1;
decltype((x)) y2 = y1;
decltype(r) r1 = y1;
decltype((r)) r2 = y2;
};
和另一个
const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = i;
decltype(i) x2;
decltype(a->x) x3;
decltype((a->x)) x4 = x3;
它们在decltype中都只有一个参数。为什么顶部代码采用两个参数(用逗号分隔)?
我创建了另一个例子(编译失败):
#include <vector>
#include <iostream>
template<class T, class F>
auto f(std::vector<T> v, F fun) -> decltype(bool(fun(v[0])), void())
{
// ...
(void)v;(void)fun;
return fun(v.size());
}
void ops(int)
{
}
int main(){
std::vector<int> v;
f(v, [](int){ return true; });
f(v,ops);
}
即使删除了行f(v,ops);
,f
模板函数的返回类型也会被计算为void。
decltype( bool( fun(v[0] ) ), void() )
使用逗号运算符。
分解它,
bool( fun(v[0] ) ), void()
由两个表达式组成;第一个
bool( fun(v[0] ) )
被评估1并丢弃,给整个表达式值
void()
其是CCD_ 4类型的值2。
decltype
然后产生表达式的类型,如上所述,该类型是void
。
这里使用逗号运算符的原因是为了确保只有当第一个子表达式有效时,整个表达式才有效;这是因为它在SFINAE中被用于在第一个子表达式无效的情况下将其从替换考虑中排除。
这是因为尽管decltype
在语法上看起来像一个函数,但它实际上是一个语言构造,(像sizeof
一样)被定义为接受单个参数。插入逗号运算符参数可能更清楚:
decltype( ( bool( fun(v[0] ) ), void() ) )
备注
- 表达式
bool( fun(v[0] ) )
实际上并没有被求值,因为我们处于一个未求值的上下文中(decltype
,类似于sizeof
)。这里重要的是,如果表达式作为一个整体进行了求值,则它将被求值,因此,如果子表达式无效,则整个表达式无效 void()
并不是真正的值,但它的行为类似于逗号运算符和decltype
上下文中的值
decltype
在括号之间生成表达式的类型,而不实际对其求值(在接下来的部分中请记住这一点)。
,
运算符计算左边的参数/表达式,丢弃结果,计算右边的参数,然后得出结果。因此,返回类型变为void
。
对于bool(fun(v[0]))
部分,这相当容易。CCD_ 18根据调用CCD_。如果f
的返回类型不能转换为bool
,这将触发一个错误,由于在decltype
内部,这将导致SFINAE(这被称为"表达式SFINAE")。
f(v[0])
将把v[0]
的返回值传递给类型为T&
的f
。如果f
没有T&
可转换的参数,或者使用更多/更少的参数,这将触发错误,并再次导致SFINAE,原因与上述相同。
(如果std::vector
不支持operator[]
,也会发生同样的情况。)
- 访问者访问变体并返回不同类型时出错
- 我的模板类方法返回错误类型?
- C++ - 声明指向返回任何类型并获取任意数量参数的函数的指针
- 为什么函数名不能与返回名类型相同?
- 如何在模板中返回正确类型的数据?
- 返回派生类型时出现协变类型错误
- 当你只使用 return 时,函数返回什么类型;在 c++ 中
- 函数的返回值类型是别名 ***或 *** 布尔值
- 有没有办法改变概念中的复合需求返回的类型?
- 在C++如何从数组中提取成员并返回成员类型的数组?
- 如何在 c++ 中从 switch 语句返回不同类型的变量
- C++如何使虚拟函数返回任何类型的指针
- 返回各种类型的函数的SWIG类型映射
- 如何为返回特定类型的函数创建 SWIG 类型图
- 更改 Python 切换的 C 函数的返回值类型
- 如何修复用于根据参数返回不同类型的模板类中的错误C2679?
- 为什么我的函数不返回点类型?
- 如何返回 QVariant 类型数组
- 用 decltype 和 auto 推导出 const(返回)类型
- 元函数使用 decltype 返回元素类型