Complex initialization for a const variable

I have seen in a lot of places code like int i; if(someConditionIstrue) { Do some operations and calculate the value of i; i = some calculated value; } use i; //Note this value is only used not changed. It should not be changed. But unfortunately in this case there is no way to guarantee it. so now if some one comes and does

i = 10;// This is valid

What i was thinking: is there a way to tell that "i" can be set only once? After that it will be a constant. Something like

const once int i; if(someConditionIstrue) { Do some operations and calculate the value of i; i = calculated value; } use i; //Note this value is only used not changed. i = 10;// Compiler error

Related

45 Responses

I’ve used this idiom from the beginning and it is indeed powerful.
However, it’s still verbose compared to the initial code, so I hope more terse notations (and automatic generalization) will get in the standard ASAP.

I get the point but I seriously doubt if it is an advantage. It is not much different from calling a named function. If the complex calculation has a name I would a create a function with that name and call it with the necessary parameters. It is more explicit, well-understood, reusable, and more portable. You could also use the ternery operator: const int i = (condition) ? complex_func(args) : some_default_value; With a lambda, you are saving creating a function and jumping to that part of the code. It is not modular, however. With a function, you can use that same logic in more places if you need to. I would not copy-paste the lambda. Any day, I would prefer to reduce the number braces I’ve to keep track of. lambdas add braces and a sneaky pair of parenthesis at the end.

The problem with named functions is that they have a name, so they can be used more than once.
When it is not the intention, it is a problem. Using a lambda makes it clear that there should be only one unique specifically located use.

Unfortunately it’s more verbose than using a named function, which can be fixed with a simpler notation.

To Johannes, In addition to not needing a name and being unique as mjklaim points out, a lambda can use scoped variables and is defined and used at the site where it is needed, making a lambda a superior choice to a non-member function in this case. Given the syntactic and semantic needs of C++, I think the current lambda notation is quite compact and the upcoming upgrades for it will only make it more seamless.

A statement like

const int i = [&] …expression…;

is more terse but if you only have a single expression it won’t make sense to use a lambda in this case. How would you like to see the the construction formed? (Using wished-for C++ language changes, if necessary)

It’s neat that they have different but overlapping uses in C++. C++ doesn’t quite have the scoping issues as JavaScript, but they can be used for some similar scenarios to those mentioned in the Wikipedia page above.

You are hiding the verbosity of the lambda in the ellipse.
If you need a lambda in this context, you will certainly do at least some kind of branching, which mean for clarity your lambda will not be a one-liner. You can use terse if syntax but then there is no need for a lambda.

With a named function, if your code looks like it’s noise in the middle of the code which use the constant, at least the code is out of the scope.
Which is a problem as you pointed, which is why I think a lambda is still better even if it looks like noise at first.

While technically the lambda is a good solution and may have its applications for initializations, in this case I’d as well recommend using a separate function. When the main task of a function is to *use* i, then the SRP demands separating the calculation of the initial value of i from the function. That way the main logic of the function is not interrupted and cluttered with a multiline lambda containing the lower level logic of the constant’s calculation.

constexpr keyword has been added for this purpose isn’t it? Using a named constexpr function is a good way to achieve the result.
Even if it adds a name in the symbol space, it could (it should in fact) be a private function within the class we’re working in.

@Herb: While your example compiles in g++4.7, 4.8 and Clang 3.2, I believe it is not a valid C++11 code. According to sect 5.1.2 para 4, when the body of the lambda is not a simple return statement its deduced return type is void. While the expectation that this example would work is logical, and likely acceptable in C++14, C++11 seems to refuse it.

@Andrzej: Right, but I’ll let it stand. The committee has already pretty much agreed that this should be allowed (which is why our compiler also already supports it, and with GCC and Clang that would make it de facto portable), and this extension is likely to be voted into the C++ working paper soon (this month, or September). I’ll go out on a limb and say that if anything is a slam dunk for C++14, it would seem that this is. And it truly should just work.

Incidentally, this is one reason why I think I’ll write Exceptional C++14… 14 is so close to done (we hope to technically finalize it in September of this year), and the delta from 11 is pretty small but with a number of convenient fit-and-finish tidy-ups like this one.

I agree with the reasons given why this is better than extracting a named helper function that is only used here: the lambda has better locality, is arguably more readable, and lets you use other locals directly without passing references to an artificially outlined function. I also agree that it’s better than “const int& i = temp_i;” which is less direct and also has the drawback that temp_i stays in scope.

The lambda solution seems appropriate for some situations, but it’s not clear that it addresses the original question.

The original question didn’t have a default value and only conditionally initializes the variable. The lambda solution doesn’t do the same thing, since it always initializes the variable regardless of the condition.

When I first read the question, I wondered if the intent was that i was actually a member variable (or at least persistent beyond the scope suggested), and the intent was to initialize it the first time SomeCondition was true and then never to change it again after that. In that case, the idea of “const once” seems useful.

For example, if i was a function static, the intent might be to initialize i the first time the function is called and the condition is true, and never to change i again after that. (And also to let i remain uninitialized until that first call with the condition being true.)

Otherwise, you could just write:

const int i = (someCondition) ? calc() : default_value;

This is going to be recognized by all C and C++ programmers, even those not versed in lambdas.

This expensive-lazy-initialisation is quite frequent in the legacy code bases I’ve dealt with (a slight improvement over repeated-initialisation – obviously there to absorb excess processing capacity).

Where the thing to be initialised is a global computed constant, as opposed, say, a constant for an object instance, I usually extract it to a static with an initialising function, such as:

namespace { // anonymous
int once_calculate_i_ () { /* … */ }
}

void foo ()
{
static const int i= once_calculate_i_ ();
// …
}

I don’t see an advantage in using a lambda here (and we’re unlikely to see C++11 compilers adopted for 10 years if past record is maintained – there are reasons for this in my domain).

I would still want to see the intent of the calculation documented, which is better handled when it is expressed as a separate function. Without documentation of intent, we have to infer intent from the implementation, which is not necessarily the same thing… Poor documentation is a bane of maintaining long-term code bases, and I prefer to leave my future incarnates something more manageable.

@Arne: No, that doesn’t work. You only get automatically thread-safe initialization for *function local* statics, not for all statics because that would incur expense on a lot of code that doesn’t need it. This is described in 3.6.2/2 for those following along in the standard. The standard way to write thread-safe initialization of statics or lazy initialization, if you’re not using function local statics, is to use once_flag and call_once.

Thanks for the enlightenment about thread safety – one question to the call_once, though: As far as I can see in N3337, there is only void call_once(once_flag&, Callable, Args&&…) – is that going to change?

@Herb, Does the first singleton example you posted imply a memory barrier? If instance() is performance-critical for subsequent calls, would an alternative be to ensure the calculation is done at startup instead of on-demand?

@Arne: What would you like to change? That signature accepts call_once( flag, []{ …my lambda… } ); right? std::async is the same.

@Jon: It can be made fast. Certainly you can do DCL, which is an atomic load (generally cheap). And before thread-safe init for function local statics was adopted, Google showed the committee a cool algorithm to do it cheaply on the fast path and promised to make the algorithm freely available for this purpose, which is what convinced the committee to adopt it as I recall. I can hunt it up in the papers but don’t have a link offhand.

[…] over adding keywords. Herb Sutter has described C++14 as an incremental update to C++11 as “the delta from 11 is pretty small but with a number of convenient fit-and-finish tidy-ups&#82…, so maybe that indicates sweeping changes like this won’t get far in […]

Hmm… one argument in favor of these options is that if those local variables are so related that they’re initialized together, they probably ought to benefit from being grouped together anyway.

In fact, in the case of host and port, the answer seems clear that the normal term we use for “initialize multiple variables that should be initialized together and probably share an invariants” is “constructor.” In the host+port example above, I sense that there’s a class or struct abstraction missing anyway to group these together, and once you have that you’re back in the simple single-variable case.

As you mentioned Scala, I was going to point out in my original post that Java also accommodates this (which may be what makes it possible for Scala’s compiler back end) with its “final” keyword. Qualifying a variable as final—like using “val” rather than “var” in Scala—means that the variable must be assigned exactly once before use, not that it needs to be bound at its point of declaration.

Yes, as sdeetee pointed out, this is very similar to a construct used in Javascript to create an object, immediately call it and use the return value from it. in javascript it is often used as a constructor, or factory pattern, but this is also another neat way to use it.