c++ - ¿Hay algún truco ninja para hacer que una variable sea constante después de su declaración?
c++11 const-correctness (7)
¿Por qué no refactorizar su código en dos funciones separadas? Uno que devuelve un a modificado y otro que funciona con este valor (sin cambiarlo nunca).
También podría envolver su objeto alrededor de un objeto de clase de soporte y trabajar con este soporte.
template <class T>
struct Constify {
Constify(T val) : v_( val ) {}
const T& get() const { return v_; }
};
void SomeFuncion() {
Constify ci( Compute() ); // Compute returns `a`
// process with ci
}
Su ejemplo tiene una solución fácil: refactorización.
// expect a lowercase path or use a case insensitive comparator for basic_string
void OpenFile(string const& path)
{
// I want path to be constant now
ifstream ...
}
OpenFile( boost::to_lower(path) ); // temporaries can bind to const&
Sé que la respuesta es 99.99% no, pero pensé que valía la pena intentarlo, nunca se sabe.
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
// From this point on I want to make "a" const; I don''t want to allow
// any code past this comment to modify it in any way.
}
Puedo hacer algo similar con const int b = a;
, pero en realidad no es lo mismo y crea mucha confusión. Una solución solo C ++ 0x es aceptable.
EDIT : otro ejemplo menos abstraído, el que me hizo hacer esta pregunta:
void OpenFile(string path)
{
boost::to_lower(path);
// I want path to be constant now
ifstream ...
}
EDITAR : otro ejemplo concreto: Recuperar la constidad de las variables en una sección paralela .
Claro, no hay forma de hacerlo usando el mismo nombre de variable en C ++.
En realidad, no sugiero hacer esto, pero podrías usar sombras variables creativas para simular algo como lo que quieres:
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
{
const int b = a;
const int a = b; // New a, shadows the outside one.
// Do whatever you want inside these nested braces, "a" is now const.
}
}
Puede mover el código para generar a
en otra función:
int ComputeA(int a) {
a *= 50;
a %= 10;
if (example())
a = 0;
return a;
}
void SomeFunction(const int a_in) {
const int a = ComputeA(a_in);
// ....
}
De lo contrario, no hay una buena manera de hacerlo en tiempo de compilación.
Un patrón que solía utilizar es "ocultar" el argumento con un _, por lo que el código se convierte
void SomeFunction(int _a)
{
// Here some processing happens on a, for example:
_a *= 50;
_a %= 10;
if(example())
_a = 0;
const int a = _a;
// From this point on I want to make "a" const; I don''t want to allow
// any code past this comment to modify it in any way.
}
También puede usar solo variables const y hacer una función para calcular el nuevo valor de a, si es necesario. Tiendo más en más para no "reutilizar" variables en hacer lo más posible mis variables inmutables: si cambias el valor de algo, entonces dale un nombre nuevo.
void SomeFunction(const int _a)
{
const int a = preprocess(_a);
....
}
Una solución sería factorizar todo el código de mutación en una expresión lambda. Haga toda la mutación en la expresión lambda y asigne el resultado a un const int
en el alcance del método. Por ejemplo
void SomeFunction(const int p1) {
auto calcA = [&]() {
int a = p1;
a *= 50;
a %= 10;
if(example())
a = 0;
..
return a;
};
const int a = calcA();
...
}
esta podría ser una forma de hacerlo, si solo está tratando de evitar otro nombre. te sugiero que lo pienses dos veces antes de usar esto.
int func ()
{
int a;
a %= 10;
const int const_a = a;
#define a const_a
a = 10; // this will cause an error, as needed.
#undef a
}