2015-11-14 3 views
3

я работал над программой недавно, которая выглядит следующим образом: -проверка константность с использованием type_traits

#include <iostream> 
#include <memory> 
#include <type_traits> 
#include <typeinfo> 
using namespace std; 

int main() 
{ 
    shared_ptr<int> sp1 = make_shared<int>(5); 
    shared_ptr<const int> sp2 (sp1); 
    const int x = 8; 

    // *sp2 = 7; // error: assignment of read-only location 'sp2.std::shared_ptr<const int>::<anonymous>.std::__shared_ptr<_Tp, _Lp>::operator*<const int, (__gnu_cxx::_Lock_policy)2u>()' 

    auto p = sp2.get(); 

    cout << typeid(x).name() << '\t' << typeid(*p).name() << '\n'; 

    cout << boolalpha; 
    cout << is_const<decltype(*p)>::value << '\n' << is_same<const int, decltype(*p)>::value; 

    return 0; 
} 

Вывод этой программы является: -

i i 
false 
false 

Как видно ясно, typeid указывает, что *p & x имеют одинаковый тип &, используя *sp2 = 7. Тогда почему std::is_same & std::is_const отличается от этого?

ответ

3

Здесь вы столкнулись с двумя различными проблемами. Первый случай мы можем видеть из записи cppreference для typeid что константные отборочные верхнего уровня игнорируется:

Во всех случаях, CV-отборочный игнорируется TypeID (то есть, TypeId (T) == TypeId (сопзИте T))

Мы можем видеть из записи cppreference для decltype следующие правила, которые имеют отношение здесь:

  1. е аргумента является Ид в скобки, выражение или ПАООН рендеризованный доступ к члену класса, тогда decltype дает тип объекта, названного этим выражением. [...]
  2. Если аргумент является любое другое выражение типа Т и

[...]

  • если значение категория выражения-значение, то decltype дает Т &;

[...]

Так *p это выражение и не является Ид выражение, ни доступ к члену класса в отличие от, скажем, следующий случай:

const int x = 0 ; 
std::cout << is_const<decltype(x)>::value << "\n" ; 
         ^^^^^^^^^^^ 

Какой бы return true, так как x является id-выражением.

Таким образом, *p, являющийся выражением, даст T&, так как результат является значением lvalue. Ссылка не будет сама быть константной так is_const правильно, с другой стороны, это будет возвращать результат вы хотите:

is_const<std::remove_reference<decltype(*p)>::type>::value 
     ^^^^^^^^^^^^^^^^^^^^^ 

Обратите внимание на использование std::remove_reference.

T.C. что std::remove_pointer также может быть эффективным:

is_const<std::remove_pointer<decltype(p)>::type>::value 
+0

nvm, confused 'p' /' sp'.Хотя я бы пошел на 'remove_pointer ' в этом случае (или перейдите через 'pointer_traits :: element_type', хотя это может быть излишним - у него есть преимущество работы как с простыми, так и с умными указателями). –

+0

@ T.C. хорошо, это имеет смысл, отредактировал ответ –

+0

круто, спасибо тонну !!! – Anwesha

 Смежные вопросы

  • Нет связанных вопросов^_^