Static data member with initializer - c++

Assuming one is never odr-used, is there a benefit of declaring a static const or static constexpr data member with an initializer over declaring and then defining one later? Is there a benefit to not needing a definition?

First, note that you can't define a static const data member where you declare it. The declaration doesn't become a definition no matter what you do (such as providing an initializer). However, a static constexpr data member doesn’t need a definition, and the static const data member of integral type with initializer doesn’t need a definition if it’s never ODR-used.
ODR: the One Definition Rule, in the C++11 standard §3.2 [basic.def.odr].
Providing a definition is non-trivial in a header file – for a non-template class the direct approach would lead fast to violations of the ODR, with the linker complaining. Thus a benefit of not defining is that it makes it easy to use header-only modules. And a benefit of defining is that it makes it easy to use any type whatsoever, and supports ODR-use.
There are already a host of SO questions dealing with practical solutions to the requirement of definition for ODR use, with respect to header-only modules.
The ODR has a special exemption for templates for this, and that’s the basis of one practical solution. Just provide the definition in a class template, and use a dummy argument to instantiate the template. Another practical solution is to place the definition in a function, essentially a Meyers’ singleton.

Related

Why can't we declare static variables in the class definition? [duplicate]

I have the following working code:
#include <string>
#include <iostream>
class A {
public:
const std::string test = "42";
//static const std::string test = "42"; // fails
};
int main(void){
A a;
std::cout << a.test << '\n';
}
Is there a good reason why it is not possible to make the test a static const ? I do understand prior to c++11 it was constrained by the standard. I thought that c++11 introduced in-class initializations to make it a little bit friendlier. I also not such semantic are available for integral type since quite some time.
Of course it works with the out-of class initialization in form of const std::string A::test = "42";
I guess that, if you can make it non-static, then the problem lies in one of the two. Initializing it out-of-class scope (normally consts are created during the instantiation of the object). But I do not think this is the problem if you are creating an object independant of any other members of the class. The second is having multiple definitions for the static member. E.g. if it were included in several .cpp files, landing into several object-files, and then the linker would have troubles when linking those object together (e.g. into one executable), as they would contain copies of the same symbol. To my understanding, this is exactly equal to the situation when ones provides the out-of-class right under the class declaration in the header, and then includes this common header in more than one place. As I recall, this leads to linker errors.
However, now the responsibility of handling this is moved onto user/programmer. If one wants to have a library with a static they need to provide a out-of-class definition, compile it into a separate object file, and then link all other object to this one, therefore having only one copy of the binary definition of the symbol.
I read the answers in Do we still need to separately define static members, even if they are initialised inside the class definition? and Why can't I initialize non-const static member or static array in class?.
I still would like to know:
Is it only a standard thing, or there is deeper reasoning behind it?
Can this be worked-around with the constexpr and user-defined
literals mechanisms. Both clang and g++ say the variable cannot have non-literal type. Maybe I can make one. (Maybe for some reason its also a bad idea)
Is it really such a big issue for linker to include only one copy of
the symbol? Since it is static const all should be binary-exact
immutable copies.
Plese also comment if I am missing or missunderstanding something.
Your question sort of has two parts. What does the standard say? And why is it so?
For a static member of type const std::string, it is required to be defined outside the class specifier and have one definition in one of the translation units. This is part of the One Definition Rule, and is specified in clause 3 of the C++ standard.
But why?
The problem is that an object with static storage duration needs unique static storage in the final program image, so it needs to be linked from one particular translation unit. The class specifier doesn't have a home in one translation unit, it just defines the type (which is required to be identically defined in all translation units where it is used).
The reason a constant integral doesn't need storage, is that it is used by the compiler as a constant expression and inlined at point of use. It never makes it to the program image.
However a complex type, like a std::string, with static storage duration need storage, even if they are const. This is because they may need to be dynamically initialized (have their constructor called before the entry to main).
You could argue that the compiler should store information about objects with static storage duration in each translation unit where they are used, and then the linker should merge these definitions at link-time into one object in the program image. My guess for why this isn't done, is that it would require too much intelligence from the linker.

Definition of a class's private integral constant: in the header or in the cpp file?

Subject has been addressed mostly here (Where to declare/define class scope constants in C++?)
and in particular here.
What I would like to fully understand, in case of integral constants, is there any difference between:
//In the header
class A {
private:
static const int member = 0; //Declaration and definition
};
And:
//In the header
class A {
private:
static const int member; //Only declaration
};
//In the cpp
const int A::member = 0; //Definition
(I understand that the second might have the advantage that if I change the value of the constant, I have to recompile only one file)
Side questions:
What happens for example with an inline method defined in the header that access member? Will it simply be not inlined? What would happens if, going to one extreme, all methods were defined in the header file as inline methods and all constants were defined in the cpp file?
Edit:
My apologizes: I thought it was not necessary, but I missed the fact that the member is static. My question stays, but now the code is legal.
If, as it was before the question was changed to make it static, it's a non-static member, then it can only be initialised in the constructor's initialiser list or (since 2011) in the member's declaration. Your second example was ill-formed.
If it's static, then you need a definition if it's odr-used: roughly speaking, if you do anything that requires its address rather than just its value. If you only use the value, then the first example is fine. But note that the comment is wrong - it's just a declaration, not a definition.
If you do need a definition, then it's up to you whether you specify the value in the declaration or the definition. Specifying it in the declaration allows better scope for optimisation, since the value is always available when the variable is used. Specifying it in the definition gives better encapsulation, only requiring one translation unit to be recompiled if it changes.
What happens for example with an inline method defined in the header that access member? Will it simply be not inlined?
There's no reason why accessing a data object defined in another translation unit should prevent a function from being inlined.
There are two points of view to take into account, namely visibility and addressing.
Note that the two are orthogonal, for you can actually declare the variable as initialized and still define it in a translation unit so it has an effective address in memory.
Visibility
Visibility affects the usage of the variable, and has some technical impacts.
For usage in template code as a non-type template parameter, the value must be visible at the point of use. Also, in C++11, this might be necessary for constexpr usage. Otherwise, it is not necessary that the value be visible.
Technically a visible value can trigger optimizations from the compiler. For example if (A::member) is trivially false so the test can be elided. This is generally referred to as Constant Propagation. While this may seem a good thing, at first glance, there is a profound impact though: all clients of the header file potentially depends on this value, and thus any change to this value means they should be recompiled. If you deliver this header as part of a shared library, this means that changing this value breaks the ABI.
Addressing
The rule here is quite simple: if the variable can be addressed (either passed by pointer or reference), then it needs to reside somewhere in memory. This requires a definition in one translation unit.
This is the question of data hiding. Whether you want to unveil internal class fields or not. If you are shipping a classes library and want to hide the implementation details then it is better to show in the interface as few entities as possible, then even a declaration of the private field member is too much.
I would just declare this value as a static variable inside a .cpp file.

Why can't I make in-class initialized `const const std::string` a static member

I have the following working code:
#include <string>
#include <iostream>
class A {
public:
const std::string test = "42";
//static const std::string test = "42"; // fails
};
int main(void){
A a;
std::cout << a.test << '\n';
}
Is there a good reason why it is not possible to make the test a static const ? I do understand prior to c++11 it was constrained by the standard. I thought that c++11 introduced in-class initializations to make it a little bit friendlier. I also not such semantic are available for integral type since quite some time.
Of course it works with the out-of class initialization in form of const std::string A::test = "42";
I guess that, if you can make it non-static, then the problem lies in one of the two. Initializing it out-of-class scope (normally consts are created during the instantiation of the object). But I do not think this is the problem if you are creating an object independant of any other members of the class. The second is having multiple definitions for the static member. E.g. if it were included in several .cpp files, landing into several object-files, and then the linker would have troubles when linking those object together (e.g. into one executable), as they would contain copies of the same symbol. To my understanding, this is exactly equal to the situation when ones provides the out-of-class right under the class declaration in the header, and then includes this common header in more than one place. As I recall, this leads to linker errors.
However, now the responsibility of handling this is moved onto user/programmer. If one wants to have a library with a static they need to provide a out-of-class definition, compile it into a separate object file, and then link all other object to this one, therefore having only one copy of the binary definition of the symbol.
I read the answers in Do we still need to separately define static members, even if they are initialised inside the class definition? and Why can't I initialize non-const static member or static array in class?.
I still would like to know:
Is it only a standard thing, or there is deeper reasoning behind it?
Can this be worked-around with the constexpr and user-defined
literals mechanisms. Both clang and g++ say the variable cannot have non-literal type. Maybe I can make one. (Maybe for some reason its also a bad idea)
Is it really such a big issue for linker to include only one copy of
the symbol? Since it is static const all should be binary-exact
immutable copies.
Plese also comment if I am missing or missunderstanding something.
Your question sort of has two parts. What does the standard say? And why is it so?
For a static member of type const std::string, it is required to be defined outside the class specifier and have one definition in one of the translation units. This is part of the One Definition Rule, and is specified in clause 3 of the C++ standard.
But why?
The problem is that an object with static storage duration needs unique static storage in the final program image, so it needs to be linked from one particular translation unit. The class specifier doesn't have a home in one translation unit, it just defines the type (which is required to be identically defined in all translation units where it is used).
The reason a constant integral doesn't need storage, is that it is used by the compiler as a constant expression and inlined at point of use. It never makes it to the program image.
However a complex type, like a std::string, with static storage duration need storage, even if they are const. This is because they may need to be dynamically initialized (have their constructor called before the entry to main).
You could argue that the compiler should store information about objects with static storage duration in each translation unit where they are used, and then the linker should merge these definitions at link-time into one object in the program image. My guess for why this isn't done, is that it would require too much intelligence from the linker.

Declaring static data members of normal class and class template

I read the reason for defining static data members in the source file is because if they were in the header file and multiple source files included the header file- the definitions would get output multiple times. I can see why this would be a problem for the static const data member, but why is this a problem for the static data member?
I'm not too sure I fully understand why there is a problem if the definition is written in the header file...
The multiple definition problem for variables is due to two main deficiencies in the language definition.
As shown below you can easily work around it. There is no technical reason why there is no direct support. It has to do with the feature not being in sufficient high demand that people on the committee have chosen to make it a priority.
First, why multiple definitions in general are a problem. Since C++ lacks support for separately compiled modules (deficiency #1), programmers have to emulate that feature by using textual preprocessing etc. And then it's easy to inadvertently introduce two or more definitions of the same name, which would most likely be in error.
For functions this was solved by the inline keyword and property. A freestanding function can only be explicitly inline, while a member function can be implicitly inline by being defined in the class definition. Either way, if a function is inline then it can be defined in multiple translation units, and it must be defined in every translation unit where it's used, and those definitions must be equivalent.
Mainly that solution allowed classes to be defined in header files.
No such language feature was needed to support data, variables defined in header files, so it just isn't there: you can't have inline variables. This is language deficiency #2.
However, you can obtain the effect of inline variables via a special exemption for static data members of class templates. The reason for the exemption is that class templates generally have to be fully defined in header files (unless the template is only used internally in a translation unit), and so for a class template to be able to have static data members, it's necessary with either an exemption from the general rules, or some special support. The committee chose the exemption-from-the-rules route.
template< class Dummy >
struct math_
{
static double const pi;
};
template< class Dummy >
double const math_<Dummy>::pi = 3.14;
typedef math_<void> math;
The above has been referred to as the templated const trick. As far as I know I was the one who once introduced it, in the [comp.lang.c++] Usenet group, so I can't give credit to someone else. I've also posted it a few times here on SO.
Anyway, this means that every C++ compiler and linker internally supports and must support the machinery needed for inline data, and yet the language doesn't have that feature.
However, on the third hand, C++11 has constexpr, where you can write the above as just
struct math
{
static double constexpr pi = 3.14;
};
Well, there is a difference, that you can't take the address of the C++11 math::pi, but that's a very minor limitation.
I think you're confusing two things: static data members and global variables markes as static.
The latter have internal linkage, which means that if you put their definition in a header file that multiple translation units #include, each translation unit will receive a private copy of those variables.
Global variables marked as const have internal linkage by default, so you won't need to specify static explicitly for those. Hence, the linker won't complain about multiple definitions of global const variable or of global non-const variables marked as static, while it will complain in the other cases (because those variables would have external linkage).
Concerning static data members, this is what Paragraph 9.4.2/5 of the C++11 Standard says:
static data members of a class in namespace scope have external linkage (3.5). A local class shall not have
static data members.
This means that if you put their definition in a header file #included by multiple translation units, you will end up with multiple definitions of the same symbol in the corresponding object files (exactly like non-const global variables), no matter what their const-qualification is. In that case, your program would violate the One Definition Rule.
Also, this Q&A on StackOverflow may give you a clearer understanding of the subject.

Should I use static or inline?

I am writing a header-only library, and I can’t make up my mind between declaring the functions I provide to the user static or inline. Is there any reason why I should prefer one to the other in that case?
They both provide different functionalities.
There are two implications of using the inline keyword(§ 7.1.3/4):
It hints the compiler that substitution of function body at the point of call is preferable over the usual function call mechanism.
Even if the inline substitution is omitted, the other rules(especially w.r.t One Definition Rule) for inline are followed.
The static keyword on the function forces the inline function to have an internal linkage(inline functions have external linkage) Each instance of such a function is treated as a separate function(address of each function is different) and each instance of these functions have their own copies of static local variables & string literals(an inline function has only one copy of these)
Note: this answer is for C++. For C, see caf's answer. The two languages differ.
static has two relevant meanings:
For a function at namespace scope, static gives the function internal linkage, which in practical terms means that the name is not visible to the linker. static can also be used this way for data, but for data this usage was deprecated in C++03 (§D.2 in C++03 Annex D, normative). Still, constants have internal linkage by default (it's not a good idea to make that explicit, since the usage for data is deprecated).
For a function in a class, static removes the implicit this argument, so that the function can be called without an object of the class.
In a header one would usually not use internal linkage for functions, because one doesn't want a function to be duplicated in every compilation unit where the header is included.
A common convention is to instead use a nested namespace called detail, when one needs classes or functions that are not part of the public module interface, and wants to reduce the pollution the ordinary namespace (i.e., reduce the potential for name conflict). This convention is used by the Boost library. In the same way as with include guard symbols this convention signifies a lack of module support in current C++, where one is essentially reduced to simulating some crucial language features via conventions.
The word inline also has two relevant meanings:
For a function at namespace scope it tells the compiler that the definition of the function is intentionally provided in every compilation unit where it’s used. In practical terms this makes the linker ignore multiple definitions of the function, and makes it possible to define non-template functions in header files. There is no corresponding language feature for data, although templates can be used to simulate the inline effect for data.
It also, unfortunately, gives the compiler a strong hint that calls to the function should preferably be expanded “inline” in the machine code.
The first meaning is the only guaranteed meaning of inline.
In general, apply inline to every function definition in a header file. There is one exception, namely a function defined directly in a class definition. Such a function is automatically declared inline (i.e., you avoid linker protests without explicitly adding the word inline, so that one practical usage in this context is to apply inline to a function declaration within a class, to tell a reader that a definition of that function follows later in the header file).
So, while it appears that you are a bit confused about the meanings of static and inline – they're not interchangable! – you’re essentially right that static and inline are somehow connected. Moving a (free) function out of a class to namespace scope, you would change static → inline, and moving a function from namespace scope into a class, you would change inline → static. Although it isn’t a common thing to do, I have found it to be not uncommon while refactoring header-only code.
Summing up:
Use inline for every namespace scope function defined in a header. In particular, do use inline for a specialization of a function template, since function templates can only be fully specialized, and the full specialization is an ordinary function. Failure to apply inline to a function template specialization in a header file, will in general cause linking errors.
Use some special nested namespace e.g. called detail to avoid pollution with internal implementation detail names.
Use static for static class members.
Don't use static to make explicit that a constant has internal linkage, because this use of static is deprecated in C++03 (even though apparently the deprecation was removed in C++11).
Keep in mind that while inline can’t be applied to data, it is possible to achieve just about the same (in-practice) effect by using templates. But where you do need some big chunk of shared constant data, implemented in a header, I recommend producing a reference to the data via an inline function. It’s much easier to code up, and much easier to understand for a reader of the code. :-)
static and inline are orthogonal. In otherwords, you can have either or both or none. Each has its own separate uses which determine whether or not to use them.
If that function is not sharing the class state: static. To make a function static can benefit from being called at anywhere.
If the function is relatively small and clear: inline
(This answer is based on the C99 rules; your question is tagged with both C and C++, and the rules in C++ may well be different)
If you declare the function as just inline, then the definition of your function is an inline definition. The compiler is not required to use the inline definition for all calls to the function in the translation unit - it is allowed to assume that there is an external definition of the same function provided in another translation unit, and use that for some or all calls. In the case of a header-only library, there will not be such an external definition, so programs using it may fail at link time with a missing definition.
On the other hand, you may declare the function as both inline and static. In this case, the compiler must use the definition you have provided for all calls to the function in the translation unit, whether it actually inlines them or not. This is appropriate for a header-only library (although the compiler is likely to behave exactly the same for a function declared inline static as for one declared static only, in both cases inlining where it feels it would be beneficial, so in practice there is probably little to be gained over static only).