Почему переменные-члены объекта const не являются константами
Просто задал подобный вопрос, который сводится к этому.
#include <iostream>
using namespace std;
struct A {
A() : a{1} {};
int a;
};
template <typename Which>
struct WhichType;
int main() {
const A a;
const A& a_ref = a;
const A* a_ptr = &a;
WhichType<decltype(a.a)> which_obj; // template evaluates to int
WhichType<decltype(a_ref.a)> which_ref; // template evaluates to int
WhichType<decltype(a_ptr->a)> which_ptr; // template evaluates to int
return 0;
}
Почему шаблоны не становятся const int
вместо int
?
Ответы
Ответ 1
decltype
дает вам "объявленный тип" операнда, если он не заключен в дополнительный набор круглых скобок.
Чтобы получить фактический тип выражения, то есть const int
, вам нужно написать decltype((a.a))
и т.д.
decltype
всегда возвращает ссылочный тип для выражений lvalue, отличных от имен.
Ответ 2
Когда передано имя идентификатора (или члена), он возвращает тип объявления.
Когда передано другое выражение, оно возвращает что-то более близкое к тому, что вы хотите, но ссылочное.
WhichType<std::remove_reference_t<decltype((a_ptr->a))>> which_ptr; // template evaluates to const int!
живой пример
или если вы хотите l/r ценность:
WhichType<decltype((a_ptr->a))> which_ptr2; // template evaluates to const int&
WhichType<decltype(((const A){}.a))> which_ptr3; // template evaluates to const int
вы можете добавить &&
, чтобы сделать его "реальной" ссылкой rvalue здесь.
WhichType<decltype(((A){}.a))&&> which_ptr4; // template evaluates to int&&!
живой пример.