Reputation: 3
I'm refactoring a compiler front-end, and facing a problem of const variable, which are non reversible to their non-const counterpart.
Context is the following : I have an abstract syntax tree (AST) and a symbol table which contains symbols, and I want to compute types of the ast nodes and symbols in the symbol table. I will refer the type computation part as 'Subsystem'.
Constraints are the following :
Here is a (really simplified) version of what I am talking about :
#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;
}
Which results in the following compilation error under gcc 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;
| ~~~~~~~~~~~~~~^~~
Problem is : as Symbol table and AST are passed "const" to the Subsystem, it is now impossible to get a const pointer from the returned TypeSymbol 's' value.
How can I get back to a non-const pointer in this context ? I thought about using const_cast, but it usually implies a design flaw, isn't it ?
Upvotes: 0
Views: 169
Reputation: 206717
Use of const_cast
is an option in your case.
*const_cast<Symbol*>(typeSymbol.s) = 1;
but remember that it can be dangerous some times.
If the original object was created as a const
object, you run the risk of undefined behavior.
Upvotes: 1