我正在尝试学习右值参考,作为我试图回答以下内容的练习。
如果传递的值是值(非引用),右值或左值,是否可以编写一个可以告诉(至少在运行时,如果在编译时更好)的函数?对于通用类型?我想尽可能多地提取有关类型的信息。
问题的另一种说法可能是:
我可以拥有一个类似typeid
的函数,可以尽可能多地讲述调用表达式吗?例如(理想情况下)类型是T
,{{1 }},T&
或T const&
。
例如,目前,T&&
删除了有关类型的一些信息,并且可以做得更好(如示例中const和非const引用是不连续的)。但是可以做到比typeid
好多少呢?
这是我迄今为止最好的尝试。它无法区分右值和“常量”。示例中的第一个和第二个案例。)
在任何情况下都不可能破坏案例1和案件2?既然两者最终都是左值?问题是,即使两者都是右值,这两种情况都会引发不同的行为吗?
在任何情况下,我似乎都过于复杂化了解决方案,因为我需要求助于rvalue条件转换,并最终得到了这个讨厌的代码,甚至不是100%。
typeid
也许在案件之间进行彻底解决的最终解决方案将涉及检测#include<iostream>
#include<typeinfo>
template<class T>
void qualified_generic(T&& t){
std::clog << __PRETTY_FUNCTION__ << std::endl;
std::clog
<< typeid(t).name() // ok, it drops any qualification
<< (std::is_const<typename std::remove_reference<decltype(std::forward<T>(t))>::type>::value?" const":"") // seems to detect constness rigth
<< (std::is_lvalue_reference<decltype(std::forward<T>(t))>::value?"&":"")
<< (std::is_rvalue_reference<decltype(std::forward<T>(t))>::value?"&&":"") // cannot distiguish between passing a constant and an rvalue expression
<< std::endl
;
}
using namespace std;
int main(){
int a = 5;
int const b = 5;
qualified_generic(5); // prints "int&&", would plain "int" be more appropriate?
qualified_generic(a+1); // prints "int&&" ok
qualified_generic(a); // print "int&", ok
qualified_generic(b); // print "int const&", ok
}
。
更新:我发现斯科特迈耶斯的这句话,他声称“标准有时需要constexpr
给出”错误的“答案”。 http://vimeo.com/97344493约44分钟。我想知道这是否是其中一例。
更新2015:我使用Boost TypeIndex重新审视了问题,结果仍然相同。例如使用:
typeid
在上面的例子中仍然无法区分template<class T>
std::string qualified_generic(T&& t){
return boost::typeindex::type_id_with_cvr<decltype(t)>().pretty_name();
// or return boost::typeindex::type_id_with_cvr<T>().pretty_name();
// or return boost::typeindex::type_id_with_cvr<T&&>().pretty_name();
// or return boost::typeindex::type_id_with_cvr<T&>().pretty_name();
}
和5
的类型。