我在下面的代码段中声明了一个名为pval
的变量,该变量试图在T&&
上派生T*
[T
为int
) 。根据使用abi解码的类型信息,得出的类型为int*
。
但是当我将int*
类型与decltype(pval)
进行比较时,它将返回零而不是1,这意味着它将pval
视为不同于int*
的其他类型。因此,pval
或int*
报告的错误的typeid
是is_same
,表示比较为假。
#include<iostream>
#include<string>
#include<typeinfo>
#include<cxxabi.h>
#include<type_traits>
using namespace std;
std::string classname(const std::type_info& info)
{
int status;
char* rslt=abi::__cxa_demangle(info.name(),0,0,&status);
std::string result(rslt);
free(rslt);
return result;
}
int main(int argc, char* argv[])
{
int* ptr = new int(10);
decltype(std::move(ptr)) pval = std::move(ptr);
cout << classname(typeid(pval)) << endl; // as per typeid information the type of pval is int*.
bool isSame = is_same<decltype(pval), int*>::value; // What then is the pval not same as int* as per is_same ?
cout << "isSame status = " << isSame << endl;
cout << is_same<int*, int*>::value << endl;
return(0);
}
答案 0 :(得分:6)
decltype
和typeid
的行为是不同的。
pval
的确切类型是int* &&
,即对int*
的右值引用。 (这就是std::is_same
与false
类型进行比较时返回int*
的原因。)根据decltype
的行为,
如果表达式的值类别为xvalue,则decltype产生T &&;
std::move(ptr)
返回的是xvalue。
以下表达式是xvalue表达式:
- 函数调用或重载的运算符表达式,其返回类型是对对象的右值引用,例如
std::move(x)
;
然后给定decltype(std::move(ptr)) pval
,pval
的类型将为int* &&
。
另一方面,typeid
的行为是不同的。
引用表示类型
std::type_info
的{{1}}对象。如果type
是引用类型,则结果引用一个表示引用类型的type
对象。
这意味着std::type_info
返回的std::type_info
对象将引用所引用的类型,即typeid(pval)
,而不是int*
。
BTW:std::type_info::name
返回的内容是实现的定义。
答案 1 :(得分:2)
__cxa_demangle()
函数无法为您提供有关const和引用限定符的可靠(或任何信息)。试试这个代替您的classname()
函数:
template <typename T, bool WithCVCorrections = true>
std::string type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own(
abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr),
std::free
);
std::string r = (own != nullptr) ? own.get() : typeid(TR).name();
if (WithCVCorrections) {
if (std::is_const<TR>::value)
r += " const";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
}
return r;
}
...是基于Howard Hinnant的代码here。明显的警告:仅适用于某些编译器(不适用于MSVC)。