Недопустимое преобразование из «const T*» в «T*» с использованием псевдонимов типов

Я использую псевдонимы типов для pointer и const pointer и не понимаю, почему существует разница между возвратом const pointer и const_pointer.

Я предположил, что const pointer в данном случае эквивалентен const int*, но получаю неверную ошибку компиляции преобразования:

ошибка: недопустимое преобразование из 'const int*' в 'S::pointer {aka int*}

struct S
{
  using pointer = int*;
  using const_pointer = const int*;

  // const_pointer get() const { return &i; }    // OK
  const pointer get() const { return &i; } // ERROR

  int i = {};
};
    
int main()
{
  const S s;
  s.get();
}
const int* — изменяемый указатель на const int. Ваш const pointer — это константный указатель на изменяемый int.
Drew Dormann 01.05.2024 19:37

В этом разница между const (int*) и (const int)*.

Mark Ransom 01.05.2024 19:38

Я предпочитаю сообщения об ошибках Clang: error: cannot initialize return object of type 'const pointer' (aka 'int *const') with an rvalue of type 'const int *'. const pointer и pointer const одинаковы.

jabaa 01.05.2024 19:38

Разница в том, что такое const. В const_pointer целое число — константа, в const pointer указатель — константа.

john 01.05.2024 19:44

Вся ваша const путаница исчезнет, ​​если вы будете постоянно ставить const справа. pointer const и int* const означают одно и то же и, очевидно, отличаются от const_pointer (также известного как int const*).

Miles Budnek 01.05.2024 19:44

@MilesBudnek Я думаю, что отчасти путаница здесь заключается в том, что новички не понимают, что указатель и то, на что он указывает, - это две разные вещи.

john 01.05.2024 19:46

@john Это может быть правдой, но даже для людей с немного большим опытом работы с C++ тот факт, что const pointer — это не то же самое, что вы получили бы при простом текстовом расширении псевдонима (то есть const int*), является нелогичным.

Miles Budnek 01.05.2024 19:53

Как говорят мудрые древние: «ведущая константа вводит в заблуждение».

StoryTeller - Unslander Monica 01.05.2024 21:21
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
86
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я считаю, что будет полезно, если вы перестанете ставить const слева. Если я перефразирую ваш вопрос:

struct S
{
  using pointer = int*;
  using const_pointer = int const*;
  using pointer_const = int*const;

  // const_pointer get() const { return &i; }    // OK
  // pointer_const get() const { return &i; }    // ERROR
  pointer const get() const { return &i; } // ERROR

  int i = {};
};

int main()
{
  const S s;
  s.get();
}

Я заменил const int* на int const*. Как правило, в C++ const в типе применяется к компоненту типа слева. Только когда слева нет шрифта, это нарушает это правило.

Когда слева нет компонента, он смотрит на локальное выражение типа, где добавляется const. Он перемещается «на один шаг вправо» и следует правилу «применить слева». Так:

const pointer

становится

pointer const 

И это становится

int*const

нет

int const*

Вторая часть заключается в понимании того, что «указатель на const int» отличается от «константного указателя на неконстантный int». В одном случае мы указываем на то, что не можем изменить; в другом мы не можем указать, на какой объект указываем, но можем изменить этот объект.

Как только вы перестанете разрешать «const слева» — как только вы переведете (по крайней мере, в уме), где const находится слева, на то, что находится справа от того, что он модифицирует, — большая путаница исчезнет.

Последняя часть путаницы заключается в том, что преобразование «слева» в «справа» касается типа, как описано, где находится const, а не полного фактического развернутого типа.

Именно поэтому я не ставлю const слева. Набирать текст легко, если вы читаете справа налево и const находится в правильном месте. int const* => Pointer to Const Int и int*const => Const Pointer to int

Loki Astari 01.05.2024 20:09

@MartinYork Восток — лучший, Запад — худший!

Yakk - Adam Nevraumont 01.05.2024 22:14

Другие вопросы по теме