P
publictom
I just happened to read item 47, "Control Flow", in Exceptional C++ by
Herb Sutter (which is based on Guru of the Week 12), just after reading
item 33, "Use Inlining Judiciously", in Effective C++ by Scott Meyers.
Now I'm a little confused.
Scott Meyers says that if an inline function can't be inlined by the
compiler it is treated like a normal non-inlined function. However, he
says that there is an older behaviour where compilers would treat the
function as static, so there would be multiple copies of it, one in
each translation unit that uses the function. He says the latter
behaviour is non-standard but (was at the time, 1998...?) widespread
enough that you should be aware of it.
Skipping to Herb Sutter's book, published 2 years later, there is the
following code:
// [This declaration comes from some other header file]
extern int fileIdCounter;
....
// Helpers to automate class invariant checking.
template<class T>
inline void AAssert( T& p )
{
static int localFileId = ++fileIdCounter;
if( !p.Invariant() )
{
cerr << "Invariant failed: file " << localFileId
<< ", " << typeid(p).name()
<< " at " << static_cast<void*>(&p) << endl;
assert( false );
}
}
This is at the start of a chunk of example code designed to illustrate
things that can go wrong with control flow. The only problem that the
book points out with the variable localFileId is that fileIdCounter
might not be initialised by the time the first copy of localFileId is
initialised. (Aside: Aren't function static variables initialised the
first time the function is executed, ie. after all globals are
initialised? I'm not sure I understand this problem)
It seems to me, though, that aside from the problem of the order of
initialisation, this code would only work as intended if the function
was not successfully inlined, and then only on a compiler that followed
the incorrect (according to Meyers) behaviour of treating the
non-inlined inline function as local to the translation unit.
If the function was successfully inlined, or if the compiler followed
the standard behaviour of treating the function as a normal non-inlined
function if it can't inline it, wouldn't there just be a single copy of
localFileId, initialised once, in the whole program, thus defeating the
object of using it to identify the file? Although this would be a
control flow problem, "Exception C++" doesn't mention it, and neither
do any of the posts I could find for the corresponding Guru of the
Week, so I think I must have misunderstood something.
I was wondering whether the fact the function is a template might have
some effect, but I found this:
"A namespace scope template function has internal linkage if it is
explicitly declared static. No other template function has internal
linkage. The inline function specifier does not affect the linkage of a
template function."
at
http://publib.boulder.ibm.com/infoc...om.ibm.vacpp6m.doc/compiler/ref/tutmplat3.htm.
Can anyone help?
Herb Sutter (which is based on Guru of the Week 12), just after reading
item 33, "Use Inlining Judiciously", in Effective C++ by Scott Meyers.
Now I'm a little confused.
Scott Meyers says that if an inline function can't be inlined by the
compiler it is treated like a normal non-inlined function. However, he
says that there is an older behaviour where compilers would treat the
function as static, so there would be multiple copies of it, one in
each translation unit that uses the function. He says the latter
behaviour is non-standard but (was at the time, 1998...?) widespread
enough that you should be aware of it.
Skipping to Herb Sutter's book, published 2 years later, there is the
following code:
// [This declaration comes from some other header file]
extern int fileIdCounter;
....
// Helpers to automate class invariant checking.
template<class T>
inline void AAssert( T& p )
{
static int localFileId = ++fileIdCounter;
if( !p.Invariant() )
{
cerr << "Invariant failed: file " << localFileId
<< ", " << typeid(p).name()
<< " at " << static_cast<void*>(&p) << endl;
assert( false );
}
}
This is at the start of a chunk of example code designed to illustrate
things that can go wrong with control flow. The only problem that the
book points out with the variable localFileId is that fileIdCounter
might not be initialised by the time the first copy of localFileId is
initialised. (Aside: Aren't function static variables initialised the
first time the function is executed, ie. after all globals are
initialised? I'm not sure I understand this problem)
It seems to me, though, that aside from the problem of the order of
initialisation, this code would only work as intended if the function
was not successfully inlined, and then only on a compiler that followed
the incorrect (according to Meyers) behaviour of treating the
non-inlined inline function as local to the translation unit.
If the function was successfully inlined, or if the compiler followed
the standard behaviour of treating the function as a normal non-inlined
function if it can't inline it, wouldn't there just be a single copy of
localFileId, initialised once, in the whole program, thus defeating the
object of using it to identify the file? Although this would be a
control flow problem, "Exception C++" doesn't mention it, and neither
do any of the posts I could find for the corresponding Guru of the
Week, so I think I must have misunderstood something.
I was wondering whether the fact the function is a template might have
some effect, but I found this:
"A namespace scope template function has internal linkage if it is
explicitly declared static. No other template function has internal
linkage. The inline function specifier does not affect the linkage of a
template function."
at
http://publib.boulder.ibm.com/infoc...om.ibm.vacpp6m.doc/compiler/ref/tutmplat3.htm.
Can anyone help?