C ++中T *类型的std :: move的异常行为

时间:2018-11-01 10:18:37

标签: c++ c++11 decltype typeid value-categories

我在下面的代码段中声明了一个名为pval的变量,该变量试图在T&&上派生T* [Tint) 。根据使用abi解码的类型信息,得出的类型为int*

但是当我将int*类型与decltype(pval)进行比较时,它将返回零而不是1,这意味着它将pval视为不同于int*的其他类型。因此,pvalint*报告的错误的typeidis_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);
}

2 个答案:

答案 0 :(得分:6)

decltypetypeid的行为是不同的。

pval的确切类型是int* &&,即对int*的右值引用。 (这就是std::is_samefalse类型进行比较时返回int*的原因。)根据decltype的行为,

  

如果表达式的值类别为xvalue,则decltype产生T &&;

std::move(ptr)返回的是xvalue

  

以下表达式是xvalue表达式:

     
      
  • 函数调用或重载的运算符表达式,其返回类型是对对象的右值引用,例如std::move(x);
  •   

然后给定decltype(std::move(ptr)) pvalpval的类型将为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)。