3

Possible Duplicate:
Is there some ninja trick to make a variable constant after its declaration?

Sometimes in C or C++ we have a variable that might be const, but we have to take some lines of code to initialize it.

Is there a way to tell the compiler that, from some point in a function, some already constructed variable has to be considered as const, until its scope ends?

Something like:

int c = 0;
// the value of c is initialized here
switch(someVar) {
   case foo: c = 3; break;
   case bar: c = 4; break;
   default : c = 42; // what else?
}
// now c is constant
ASSUME_CONST_FROM_NOW(c) // some #pragma maybe?

I know that I could initialize the variable in a dedicated function. This is not really what I am asking for.

Another example:

int c = 0; int d = 0;
{ /*some block of code that initializes both c and d jointly*/ }
ASSUME_CONST_FROM_NOW(c, d)

There is no function that can return two values at a time without creating structures or classes.

But such a trick could be useful in order to make old, crappy code more easily understandable with not much refactoring.

Community
  • 1
  • 1
Benoit
  • 76,634
  • 23
  • 210
  • 236
  • @MSalters: thanks, had not seen that one. – Benoit Jan 14 '11 at 10:14
  • Why would you want to do that? More specifically, why is it so important, that you'd be ready to use non-standard and not-portable #pragma's to achieve this? Anyway, basically (in C) you can't "constify" a non-const variable. Once a variable is non-const, you can (should you want) safely cast away any const-qualifiers to access that variable. – eq- Jan 14 '11 at 10:26
  • It's not an exact duplication, because there is no hint on allowing C++0x solutions in this question. Trying to come up with a complicated C++03 solution for the other question would be a bad/unnecessarily-complex answer. For this question as currently stated, it would be a necessarily-complex answer. – Johannes Schaub - litb Jan 14 '11 at 10:32

3 Answers3

9

Yes.

Put the initialization in a function.

int getInitCValue(int const& someVar)
{
    // the value of c is initialized here
    switch(someVar)
    {
        case foo: return 3;
        case bar: return 4;
        default : return 42; // what else?
    }
}

int const c = getInitCValue(someVar);

Edit: To answer the modified question.

You want to initialize two values:

std::pair<int,int> const value = initalizePairOfValues(someValue);
int const& c = value.first;
int const& d = value.second;

Edit 2: Go with Péter Török deleted solution (Peter if you un-delete I will remove this).

struct ConstValues
{
    ConstValues()
    {
         switch(....)
         // Initialize C/D
    }
    int const& getC() const {return c;}
    int const& getD() const {return d;}
    private:
       int c;
       int d;
};
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 1
    ...you mean initialize via a function? – Nim Jan 14 '11 at 10:07
  • This is exactly what I told in the end of my question. I know this is the way I should do it. But sometimes this advice would lead to too much work. Sometimes, also, be could initialize two variables in the same time. – Benoit Jan 14 '11 at 10:08
  • @Benoit: You are wright you can't return two values without making a class. But you can use a class that already exists. std::pair<> is very good for two values and boost::touple<> is very good for a set of values. – Martin York Jan 14 '11 at 10:24
  • @Benoit: use `boost::tie` with @Martin York's suggestion for this. – Alexandre C. Jan 14 '11 at 10:36
  • I think you mean `std::pair`, I corrected your post if you don't mind. – Alexandre C. Jan 14 '11 at 10:41
  • @Benoit: If the variables are that closely related, then maybe they should be in a class. Then they can be initialized in the class's constructor. – Steve M Jan 14 '11 at 15:53
9

In C++0x, you can do something like this:

int const c = []() -> int { 
    int r; 
    switch(42) { 
    case 3: 
        r = 1; break; 
    case 4: 
        r = 2; break; 
    default: 
        r = 23; 
    }; 
    return r; 
}();
etarion
  • 16,935
  • 4
  • 43
  • 66
1

If you are willing to provide some {} around the code that is to see the variable const, yes, at least something similar. Put something like the following in a macro:

#define CONSTIFY(T, NAME)                  \
for (bool p00 = true; p00; p00=false)      \
for (T p000 = NAME; p00; p00=false)        \
for (T const NAME = p000; p00; p00=false)

this should work in C99 as well as in C++. Technically, this doesn't make your original variable const but creates a new variable with the same contents for the depending scope.

And beware that in some cases (break or continue) this might change the control flow. But as long as you wrap this around something which is basically a whole function body, this should work.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • smart, but this is asking for a world of pain later... :D – Nim Jan 14 '11 at 10:50
  • @Nim: One should probably not leave this in the code, I agree. But for the purpose of checking some legacy code quickly to see if there is somewhere an attempt to change the variable, this might still help. – Jens Gustedt Jan 14 '11 at 11:06
  • Besides this, this could lead to data loss if copy constructors (like with `auto_ptr`s which, I agree, should not be used) are tricky. – Benoit Jan 14 '11 at 15:59
  • @Benoit, I am too much thinking in C nowadays. With `int` as in the question this shouldn't change much. For C++, yes indeed that already supposes that a copy constructor is accessible. Why this would lead to dataloss, I don't get. – Jens Gustedt Jan 14 '11 at 16:31
  • auto_ptr destructor calls delete[]. Therefore it should never be copied if the intent is to share the pointer, only when the owner of the pointer should be transferred. – Benoit Jan 14 '11 at 16:42