Неожиданное поведение std :: move на типе T * в C ++ - PullRequest
0 голосов
/ 01 ноября 2018

Ниже приведен фрагмент кода, где я объявляю переменную с именем 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);
}

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Поведения decltype и typeid различны.

Точный тип pval равен int* &&, т. Е. Rvalue-ссылка на int*. (Вот почему std::is_same возвращает false при сравнении его с типом int*.) Согласно поведению decltype,

если значение категории выражения равно xvalue, тогда decltype приводит к T &&;

И std::move(ptr) возвращает xvalue .

Следующие выражения являются выражениями xvalue:

  • вызов функции или перегруженное выражение оператора, тип возвращаемого значения которого является rvalue ссылкой на объект, например std::move(x);

Тогда, учитывая decltype(std::move(ptr)) pval, тип pval будет int* &&.

С другой стороны, поведение typeid отличается.

Относится к std::type_info объекту, представляющему тип type. Если type является ссылочным типом, результат ссылается на объект std::type_info, представляющий ссылочный тип.

Это означает, что объект std::type_info, возвращаемый typeid(pval), будет ссылаться на ссылочный тип, то есть int*, а не int* &&.


Кстати: что std::type_info::name возвращает, определяется реализацией.

0 голосов
/ 01 ноября 2018

Функция __cxa_demangle() не дает надежной (или какой-либо?) Информации о константных и ссылочных квалификаторах. Попробуйте это вместо вашей 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;
}

... который основан на коде Говарда Хиннанта здесь . Очевидное предостережение: это будет работать только для некоторых компиляторов (не MSVC).

...