Re: Static local objects in inline functions.
On 18 Apr., 08:29, "Peter C. Chapin" <pcc482...@gmail.com> wrote:
Hello!
I'm looking for a little clarification about the behavior of static local
objects in inline functions. Consider the following program consisting of
three files. First the header, check.hpp:
#include <iostream>
// Quick and dirty class with a noisy constructor.
class X {
public:
X( ) { std::cout << "I'm in X::X( )\n"; }
};
// This is the interesting function.
inline void f( )
{
static X object;
}
extern void g( );
Next the file check.cpp containing the main function:
#include "check.hpp"
int main( )
{
f( ); // Call the inline function.
g( ); // Hop over to another translation unit.
}
Finally the file check2.cpp containing function g():
#include "check.hpp"
void g( )
{
f( ); // Call the inline function here too.
}
When compiled with g++ v4.3.2 the constructor is only called once. However
some other compilers call the constructor twice. In those cases, it appears
that the static local object inside f( ) is duplicated in each translation
unit (and is constructed once in each translation unit).
The standard allows only a single constructor call, except if
that constructor call would fail via an exception. I exclude
this case, because there is nothing in your program which
would allow for a second call of the function and it would
terminate in this case.
Section 9.3p6 of the 2003 standard says, "A static local variable in a member
function always refers to the same object, whether or not the member function
is inline." That seems fairly clear except that I'm not 100% sure what is
meant by "the same object" in this context. When the definition of the inline
function appears in two different translation units, is it the same object in
each translation unit?
The same object just means that the multiple definitions
of the inline member function which contain the static
local variable shall behave as if this static local
object is the same object for each function. This again
implies via the initialization rules of static local
objects that it shall only be initialized *once*, see
6.7/4:
"[..] Otherwise such an object is initialized the first
time control passes through its declaration; such an
object is considered initialized upon the completion of
its initialization. [..]"
This makes pretty clear that a given local static object
can only be initialized once, but note that your quoted
wording of 9.3p6 is restricted to *member functions. The
correct quote relevant for your example is 7.1.2/4:
"[..] A static local variable in an extern inline function
always refers to the same object. [..]"
Section 7.1.2p4 says, "An inline function shall be defined in every
translation unit in which it is used and shall have exactly the same
definition in every case (3.2)"
Section 3.2 is the One Definition Rule. Section 3.2p5 says, "There can be more
than one definition of a... inline function with external linkage (7.1.2)...
provided that each definition appears in a different translation unit, and
provided the definitions satisfy the following requirements..."
One of those requirements says, "... in each definition of D [the entity with
multiple definitions], corresponding names, looked up according to 3.4, shall
refer to an entity defined within the definition of D, or shall refer to the
same entity..."
The ODR-related requirements just make clear, that inline
functions may (and need) to be defined in each translation
unit where they are used. The remaining parts you quoted
from this sub-clause just impose the requirement that
you don't trick here, e.g.:
#ifdef SOME_THING
# define TT int;
#else
# define TT long;
#endif
inline double foo() {
TT var = 0;
return var;
}
The wording requires that TT is always the same
in each translation unit where foo is defined,
otherwise this would cause undefined behaviour.
But this problem is not part of your example.
To me this leaves the central question unanswered. 9.3p6 says that static
local variables of inline functions are the "same object" and the description
of the ODR says that two definitions can exist in separate translation units
if they make use of the "same entity." Are the objects the same or not?
9.3 is only referring to member functions,
as shown above, but that is not relevant:
A function local static object has to be
the same for each inline function by
7.1.2/4 and the initialization rules
quoted above require that this object
is only required once successfully. The
ODR does not conflict with this: It
concentrates on other aspects that could
possibly have the effect that the definitions
are not the same. In this regard does the
ODR not say something special about local
static objects.
My question comes down to this... which of these possibilities is correct:
1. A conforming compiler must call X::X exactly once in my sample program
above. There is only a single object program-wide representing the static
local variable.
2. A conforming compiler must call X::X exactly twice in my sample program
above. There is a single object in each translation unit representing the
static local variable.
3. The number of calls to X::X is unspecified.
4. The program has UB.
The only valid solution is 1, assuming that the
implementation of the constructor does not throw
an exception.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]