关于获取函数结果类型的各种方法 在一个函数调用结果的类型必须被推断的上下文中,C++似乎更乐意帮助我们,至少提供以下两个解决方案:
类型特征:关于获取函数结果类型的各种方法 在一个函数调用结果的类型必须被推断的上下文中,C++似乎更乐意帮助我们,至少提供以下两个解决方案:,c++,c++14,typetraits,C++,C++14,Typetraits,类型特征: std::result_of<F(Args...)>::type std::result\u of::type 核心语言语法: decltype(std::declval<F>()(std::declval<Args>()...); decltype(std::declval()(std::declval()…); 我的问题是,两者之间有什么区别吗?是否存在一个上下文,其中一个不能被另一个替换,如果没有,为什么我们需要一个类型特征来完成
std::result_of<F(Args...)>::type
std::result\u of::type
decltype(std::declval<F>()(std::declval<Args>()...);
decltype(std::declval()(std::declval()…);
我的问题是,两者之间有什么区别吗?是否存在一个上下文,其中一个不能被另一个替换,如果没有,为什么我们需要一个类型特征来完成语言可以开箱即用的事情?
的result\u在应用于给定类型时会产生的返回类型-它甚至在中使用e> invoke
声明的返回类型。但是,invoke
所涵盖的场景远不止普通的非成员函数调用。您展示的decltype(…)
中的表达式只是的结果\u检查的众多表达式之一
因此,只有当F
被保证为函数对象类型时,您的选项才是等效的。否则result\u在decltype(…)
不是:
struct A {int i;};
decltype(std::declval<int A::*>()(std::declval<A>())) // error
std::result_of_t<int A::*(A)> // = int&&, treated as a member access
结构A{int i;};
DeCype(STD:DeCalvE)(STD::DECVALL)(注意< C++ >代码>代码>友好,如C++ 14,即无效类型导致“ASCODE > DeCype < /代码>的平滑演绎失败。” < P> >一些不太有经验的C++程序员,让他们猜测每个代码段的代码。
有多少人第一次正确?有多少人第二次正确
给这个操作起一个名字会使它更具可读性
现在,请一些有经验的C++程序员,让他们在不使用RESUTTHORE的情况下得到函数调用的结果类型。有多少人得到正确的答案,并且需要多长时间?
这已经不是一个简单的元编程了,封装它可以让谷歌更容易发现,也更容易找到正确的方法
而且,第一个版本要短一些
所以的结果是非常有用的,因为标准库本身需要它很多次,所以让程序员也可以使用它是很简单的。有三个区别
最初,
的std::result_不要求是SFINAE友好的。因此,如果要在上下文中使用它来验证F
是否可以使用Args…
调用,它将给您一个硬错误,而decltype
使用std::declval
只会导致可能的预期替换失败。修复了本规范旨在使其具有友好性
但在兼容的C++14编译器上,两者都是SFINAE友好的。std::result\u of_t
实际上是根据后者定义的。From[meta.trans.other]:
如果表达式
INVOKE(declval(),declval()…)
很好
当被视为一个整体时形成的
未赋值的操作数(第5条)
成员类型定义类型应命名
键入decltype(调用(declval(),declval()…);
否则,不得有任何成员
类型
正如
的result\u的定义中明确指出的那样,Fn
类型可以是任何INVOKE
-able,而显式调用std::declval()
只对函数和函数对象有效。因此,如果您有:
using F = decltype(&X::bar);
using T1 = std::result_of_t<F(X*)>; // ok
using T2 = decltype(std::declval<F>()(std::declval<X*>()); // not ok
这导致SFINAE失败(至少这不是一个硬错误),因为我们必须形成类型int()()
——一个返回函数的空函数。从技术上讲,我们编写的代码不正确。应该是:
template <class F, class R = std::result_of_t<F&()>>
R call_fixed(F& f) { return f(); }
模板
R调用_fixed(F&F){return F();}
这是可行的。但如果我们对德克瓦尔犯了同样的错误,我们会没事的:
template <class F, class R = decltype(std::declval<F>()())>
R call_declval(F& f) { return f(); }
模板
R调用_declval(F&F){return F();}
事实上,我不确定它是否是一个dupe。通常是关于decltype
。这一个是专门在函数调用的上下文中。第三个:如果F
或Args
中的一个是抽象的,或者F
是一个函数类型,result\u
是无效的,但是decltype
declval
可以正确工作y、 (解决方法是使用
的result\u@Barry我相信形成类型“函数返回函数”或“函数[按值获取抽象类型]按值返回抽象类型”是不可能的。@Columbo这很不幸。@Barry可能是在变量模板出现之前引入
的result\u的(最初是在年提出的)。为了传递所需的信息,他们认为使用复合函数类型既有效(与某些元组类模板相反),又有简洁的语法。后者仍然有效,IMO超过了这些特殊情况。@Columbo是的,但我不完全理解这一点。
template <class F, class R = decltype(std::declval<F>()())>
R call_declval(F& f) { return f(); }