473,748 Members | 7,142 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Can static member variables be declared "inline"?

As we know, the keyword "inline" is a bit misleading because its
meaning has changed in practice. In most modern compilers it has
completely lost its meaning of "a hint for the compiler to inline the
function if possible" (because if the compiler has the function
definition available at an instantiation point, it will estimate whether
to inline it or not, and do so if it estimates it would be beneficial,
completely regardless of whether the keyword 'inline' appears in the
function definition or not).

In fact, the keyword "inline" is in practice a linker command, not a
compiler command. It tells the linker that if it finds an instantiation
of that function in more than one object file, it should use only one of
them and discard the rest.

Also as we know, template functions and member functions of template
classes are implicitly "inline": If they are instantiated in more than
one compilation unit (and not inlined), the linker will use only one
instantiation when linking and discard the rest.

What many C++ programmers might not realize is that this implicit
inlining of template class members extends to static member variables as
well. In other words, if you do this:

// Template class header file
// --------------------------------------------
template<typena me T>
class SomeClass
{
static int memberVariable;
...
};

template<typena me T>
int SomeClass<T>::m emberVariable = 1;
// --------------------------------------------

and this header is used in more than one compilation unit, the static
member variable will also be instantiated in all those compilation
units, but this will not cause a linker error. The linker will nicely
use only one of them and discard the rest. Effectively the static member
variable has been declared "inline".

This is not only a nice feature of template classes, but a must.
Without this property it would be impossible to have static member
variables in template classes because it would be impossible to
instantiate them in only one place (if the template class is used in
more than one compilation unit).

So my question is: Why can't static member variables of regular
classes be declared "inline", like the ones of template classes?
Compilers clearly have the support for this because they must do it for
template classes. However, seemingly the C++ standard does not support
this for static members of regular classes. Or is there a way that I
don't know of?
Sep 1 '08 #1
17 8378
On Sep 2, 12:26 am, Juha Nieminen <nos...@thanks. invalidwrote:
As we know, the keyword "inline" is a bit misleading because
its meaning has changed in practice. In most modern compilers
it has completely lost its meaning of "a hint for the compiler
to inline the function if possible" (because if the compiler
has the function definition available at an instantiation
point, it will estimate whether to inline it or not, and do so
if it estimates it would be beneficial, completely regardless
of whether the keyword 'inline' appears in the function
definition or not).
Unless the compiler can be reasonably sure of making a better
estimate than you, I'd call this a bug, or at least poor quality
of implementation. And only a very few compilers are capable of
this except in very limited cases.
In fact, the keyword "inline" is in practice a linker command,
not a compiler command.
It's not a command, it's a "function specifier", which is in
some ways a bit like a "storage class specifier". It's a part
of the language, and has a specific semantic associated with the
language (it makes multiple definitions legal, provided that
they are in different sources). It also has an "intent", and it
is a poor compiler which ignores this intent (unless, as I said,
it is certain that it can do better).
It tells the linker that if it finds an instantiation of that
function in more than one object file, it should use only one
of them and discard the rest.
No. That's one aspect of some implementations , but it's not
fundamental. (And a compiler could do this with non-inline
functions as well, if it wanted to.)
Also as we know, template functions and member functions of
template classes are implicitly "inline":
No they're not, although they can also be multiply defined (and
you're forgetting export, of course).
If they are instantiated in more than one compilation unit
(and not inlined), the linker will use only one instantiation
when linking and discard the rest.
Again, implementation defined. I've used compilers that didn't
instantiate any of the template functions until link time, and
then only once.
What many C++ programmers might not realize is that this
implicit inlining of template class members extends to static
member variables as well. In other words, if you do this:
// Template class header file
// --------------------------------------------
template<typena me T>
class SomeClass
{
static int memberVariable;
...
};
template<typena me T>
int SomeClass<T>::m emberVariable = 1;
// --------------------------------------------
and this header is used in more than one compilation unit, the
static member variable will also be instantiated in all those
compilation units, but this will not cause a linker error.
Again, that's one way (not the best, but probably the most
widespread) of implementing this. It's certainly not required
by the standard.
The linker will nicely use only one of them and discard the
rest. Effectively the static member variable has been
declared "inline".
This is not only a nice feature of template classes, but a
must. Without this property it would be impossible to have
static member variables in template classes because it would
be impossible to instantiate them in only one place (if the
template class is used in more than one compilation unit).
So my question is: Why can't static member variables of
regular classes be declared "inline", like the ones of
template classes?
Because "the inline specifier indicates to the implementation
that inline substitution of the function body at the point of
call is to be preferred to the usual function call mechanism."
Which obviously doesn't make sense for variables. And "while an
implementation is not required to perform this inline
substitution", the intent is clearly expressed, and it would be
a very poor implementation which didn't perform it without a
very good reason for not doing so.
Compilers clearly have the support for this because they must
do it for template classes. However, seemingly the C++
standard does not support this for static members of regular
classes. Or is there a way that I don't know of?
Make the class a template:-).

Seriously, why do you want to do it?

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 2 '08 #2
James Kanze wrote:
[treat "inline" as "the definition is inlined into the interface"]
Seriously, why do you want to do it?
Header-only implementations of libraries (with globals) would be an
application.

Sep 2 '08 #3
cch
于 Mon, 01 Sep 2008 22:26:08 +0000,Juha Nieminenå†™åˆ°ï ¼š
As we know, the keyword "inline" is a bit misleading because its meaning
has changed in practice. In most modern compilers it has completely lost
its meaning of "a hint for the compiler to inline the function if
possible" (because if the compiler has the function definition available
at an instantiation point, it will estimate whether to inline it or not,
and do so if it estimates it would be beneficial, completely regardless
of whether the keyword 'inline' appears in the function definition or
not).

In fact, the keyword "inline" is in practice a linker command, not a
compiler command. It tells the linker that if it finds an instantiation
of that function in more than one object file, it should use only one of
them and discard the rest.

Also as we know, template functions and member functions of template
classes are implicitly "inline": If they are instantiated in more than
one compilation unit (and not inlined), the linker will use only one
instantiation when linking and discard the rest.

What many C++ programmers might not realize is that this implicit
inlining of template class members extends to static member variables as
well. In other words, if you do this:

// Template class header file
// -------------------------------------------- template<typena me T>
class SomeClass
{
static int memberVariable;
...
};

template<typena me T>
int SomeClass<T>::m emberVariable = 1; //
--------------------------------------------

and this header is used in more than one compilation unit, the static
member variable will also be instantiated in all those compilation
units, but this will not cause a linker error. The linker will nicely
use only one of them and discard the rest. Effectively the static member
variable has been declared "inline".

This is not only a nice feature of template classes, but a must.
Without this property it would be impossible to have static member
variables in template classes because it would be impossible to
instantiate them in only one place (if the template class is used in
more than one compilation unit).

So my question is: Why can't static member variables of regular
classes be declared "inline", like the ones of template classes?
Compilers clearly have the support for this because they must do it for
template classes. However, seemingly the C++ standard does not support
this for static members of regular classes. Or is there a way that I
don't know of?
The one you decalared in template is not inline, even it is in hearder
file.

The template will be extracted to regular classes whenever you use
SomeClass<type> . Different "type" will be extracted to different class.

BTW: I only heard about inline function, but not inline variables.

--
cch@srdgame
Sep 2 '08 #4
Alf P. Steinbach wrote:
* James Kanze:
>>
Seriously, why do you want to do it?

Practically, for the purpose of header-only code.
Right. If you make a very small utility class which, for example, you
want to distribute, it makes the usage of that utility much easier when
you can simply say "unpack this file into your source directory, and
then just #include it wherever you need it; nothing else is needed".

If the class happens to need a static member variable, then there's no
way around it: You must provide a source file (which might only contain
the definition of that static member variable and nothing else), and the
user will have to include this source file into his project or makefile
(or compile it separately). Sure, it's not that big of a deal, but adds
useless complication to such a small utility class, and can be a
nuisance for very small one-source-file programs.

But I suppose a trick around the problem is to indeed make the class a
template class and then create the actual type with a typedef. Perhaps
something like:

template<int i>
class TemplatedVersio nOfTheClass
{
...
};

typedef TemplatedVersio nOfTheClass<0Th eClass;

(In fact, this might even make it more efficient because only those
member functions which are really used will end up in the final
executable file. With regular classes all the member functions may well
end up there, even though some of them might never be called.)

Of course, depending on the compiler, error messages can get uglier.
Sep 2 '08 #5
cch@srdgame wrote:
The one you decalared in template is not inline, even it is in hearder
file.

The template will be extracted to regular classes whenever you use
SomeClass<type> . Different "type" will be extracted to different class.
Wrong. Even if the same static member variable is instantiated in more
than one compilation unit (because both use the template class with the
same template parameters), the linker will use only one of those
instantiations and will not give an error because of multiple
definitions. This works in the same way as inline functions (which don't
actually get inlined).
Sep 2 '08 #6
On Sep 2, 1:06 pm, Marco Manfredini <ok_nospam...@p hoyd.netwrote:
James Kanze wrote:
[treat "inline" as "the definition is inlined into the interface"]
Seriously, why do you want to do it?
Header-only implementations of libraries (with globals) would
be an application.
But why would you want to do that? If your code is all
templates, you may have to, but it's really something which
you'd want to avoid, no?

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 2 '08 #7
On Sep 2, 2:40 pm, "Alf P. Steinbach" <al...@start.no wrote:
* James Kanze:
On Sep 2, 12:26 am, Juha Nieminen <nos...@thanks. invalidwrote:
So my question is: Why can't static member variables of
regular classes be declared "inline", like the ones of
template classes?
Because "the inline specifier indicates to the implementation
that inline substitution of the function body at the point of
call is to be preferred to the usual function call mechanism."
Which obviously doesn't make sense for variables.
In other words, the standard contains this wording because it
contains this wording?
The standard contains this wording because inline expresses an
intent which only makes sense for functions, not for variables.
If you really meant that then it would be meaningless.
But I think you misunderstood Juha's point.
The simple answer is, historic accident.
'inline' came first, templates came later, and the joining
wasn't perfect, just practical enough to be useful.
I'm pretty sure that that's not true. It's more or less an
(unfortunate) accident that templates work more or less like
inline does, and it was certainly never the intent to require
this, or ban more efficient (for the programmer)
implementations . And inline was always viewed more or less like
register, in the old days: an ugly hack, necessary because
compiler technology wasn't adequate to figure it out better than
the programmer. Probably, in ten years time, or more, inline
will be considered much like register is today---and be more or
less ignored. But we aren't there yet: inline is your way of
telling the compiler that the function will be called very, very
often, and that the execution time of the actual call will be
significant in the total runtime of the program. And that just
doesn't make sense for variables.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 2 '08 #8
On Sep 2, 4:22 pm, Juha Nieminen <nos...@thanks. invalidwrote:
cch@srdgame wrote:
The one you decalared in template is not inline, even it is in hearder
file.
The template will be extracted to regular classes whenever you use
SomeClass<type> . Different "type" will be extracted to different class..
Wrong.
I don't think English is cch's native language, and his
expression isn't the clearest, but what he says is 100% correct
(although not necessarily very relevant to the issue at hand).
Even if the same static member variable is instantiated in more
than one compilation unit (because both use the template class with the
same template parameters),
Except that he explicitly said that the "type" were different.
the linker will use only one of those instantiations and will
not give an error because of multiple definitions. This works
in the same way as inline functions (which don't actually get
inlined).
And you seem to be confusing what the standard says about
"instantiat ion" and how some (not all) compilers happen to
implement it. As far as the standard is concerned, for any
given set of template arguments, instantiation takes place once,
and only once. Where exactly (in which of the various contexts
which triggered the instantiation) is not defined, and if the
results of the instantiation depend on where, the program has
undefined behavior, but there is one, and only one
instantiation. Some compilers do instantiate many times, and
count on the linker throwing out all but one, but the better
ones maintain a repository of some sort, and don't reinstantiate
if they don't have to. (Of course, getting this right is
non-trivial, and earlier versions often failed to reinstantiate
when they should have, or vice version, which has left a bad
taste in some people's mouth. But correctly implemented, it's
far superior than redoing the work n times, with n copies of the
same thing floating around.)

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 2 '08 #9
James Kanze wrote:
On Sep 2, 1:06 pm, Marco Manfredini <ok_nospam...@p hoyd.netwrote:
>James Kanze wrote:
>[treat "inline" as "the definition is inlined into the interface"]
Seriously, why do you want to do it?
>Header-only implementations of libraries (with globals) would
be an application.

But why would you want to do that? If your code is all
templates, you may have to, but it's really something which
you'd want to avoid, no?
Having the implementation and interface in one file is really handy,
because you don't have to maintain the build of the implementation file
(or even a separate library) anymore. Also it simplifies code sharing
between libraries or shared objects, because you are untroubled by
duplicate definition problems. Also, deployment is trivial and binary
compatibility a non-issue.
Sep 2 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
2782
by: Chris Mantoulidis | last post by:
I am not clear with the use of the keyword inline... I believe you add it do a function when you implement the function inside the header file where the class is stored... But is that all? What am I missing? If that's all, then why did Bjarne even bother adding it to the language? If that's not all, what else can I do with "inline"?
9
2066
by: John Rambo | last post by:
Hi, I made the following test program: //////////////////////// classes_1.cpp #include <iostream> #include "classes_1.h" using namespace std; A::A():i(0){cout <<"const A: i =" << i <<endl;} A::~A(){cout <<"destr A"<<endl;} inline void A::showA() {cout << "show A: i =" << i <<endl;}; //////////////////////// classes_1.h
14
2115
by: Frederick Gotham | last post by:
The original purpose of "inline" was that code could be "expanded in place". Of course, it has other uses... For one thing, the following two translation units will compile together succesfully into a program: /* source1.cpp */ inline int Func(double arg) {
0
8830
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9541
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9370
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9321
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9247
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8242
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6796
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4602
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
2215
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.