Как константный указатель, ссылающийся на изменяемые данные, может быть «преобразован обратно» в неконстантный указатель? - PullRequest
0 голосов
/ 14 марта 2020

Я выполняю рефакторинг внешнего интерфейса компилятора и сталкиваюсь с проблемой константной переменной, которая необратима для их неконстантного аналога.

Контекст следующий: у меня есть дерево абстрактного синтаксиса ( AST) и таблица символов, которая содержит символы, и я хочу вычислить типы узлов ast и символы в таблице символов. Я буду ссылаться на часть вычисления типа как 'Подсистема'.

Ограничения следующие:

  • Моя AST - сложная структура, поэтому я хотел бы избежать итерации по всему узлу каждый раз, когда это возможно.
  • Подсистема строится в соответствии с функциональной парадигмой, поэтому она не будет напрямую изменять что-либо (ни AST, ни таблицу символов), а только вычисляет тип и, в конечном итоге, символ, используя таблицу символов. Его параметрами являются текущий узел AST, тип которого должен быть вычислен, и таблица символов.
  • Когда подсистема вычислений завершена, я хочу сослаться на возвращенный символ как неконстантный указатель.

Вот (действительно упрощенная) версия того, о чем я говорю:

#include <string>
#include <map>

// For readability / understandability only
using Type = int;
using Symbol = int;

struct TypeSymbol {
    Type t;
    const Symbol* s;
};

TypeSymbol ComputeTypeSymbolInSubsystem(const std::map<std::string, int>& data) {

    return { 123, &data.at("bar") };
}

int main()
{
    std::map<std::string, Symbol> symbols = { {"test", 0 } , { "foo", 51 }, { "bar", 63 }, {"", 2 } };

    auto typeSymbol = ComputeTypeSymbolInSubsystem(symbols);

    // Obvious compilation error, even if "s" is still refering to a mutable memory zone (the symbols variable)
    *typeSymbol.s = 1;

    return 0;
}

, что приводит к следующей ошибке компиляции в g cc 9.2.0:

main.cpp: In function 'int main()':
main.cpp:25:19: error: assignment of read-only location '* typeSymbol.TypeSymbol::s'
   25 |     *typeSymbol.s = 1;
      |     ~~~~~~~~~~~~~~^~~

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

Как я могу вернуться к неконстантный указатель в этом контексте? Я думал об использовании const_cast, но обычно это подразумевает недостаток дизайна, не так ли?

1 Ответ

1 голос
/ 14 марта 2020

Использование const_cast является опцией в вашем случае.

*const_cast<Symbol*>(typeSymbol.s) = 1;

, но помните, что это может быть опасно несколько раз.

Если исходный объект был создан как const объект, вы рискуете неопределенного поведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...