What are the storage classes in D? - d

Up until now I was under the impression that things like immutable and const were storage classes. In a recent video (at around 11:55) Walter Bright states that immutable is not a storage class, but rather it's a type constructor. In the official documentation, immutable, const, and among many other keywords, are listed as being storage classes:
StorageClass:
abstract
auto
const
deprecated
enum
extern
final
immutable
inout
shared
nothrow
override
pure
__gshared
Property
scope
static
synchronized
Is this list wrong? Some of it doesn't make sense(e.g., deprecated, override).
I know static and ref are storage classes, but what's the rest? And which one of the keywords in D are type constructors?

I would point out that there is a big difference between a grammar rule named StorageClass, and what is semantically a storage class in the language. The grammar rules have to do with parsing, not the semantic phase of compilation.
First off, TDPL, chapter 8, is explicitly about type qualifiers (for which Walter used the term type constructor). There are only 3 of them in D:
const
immutable
shared
All three of them are a part of the type that they modify. Such is not true with storage classes such as ref.
inout is what TDPL calls a "wildcard qualifier symbol," so it's a placeholder for a type qualifier rather than really being either a type qualifer or a storage class.
Now, as to what's a storage classes or not, I give two quotes from TDPL:
Each function parameter (base and exponent in the example above) has, in addition to its type, an optional storage class that decides the way that arguments are passed to the function when invoked.
(from pages 6 - 7)
Although static is not related to passing arguments to functions, discussing it here is appropriate because, just like ref, static applied to data is a storage class, meaning an indication about a detail regarding how data is stored.
(from page 137)
Also, there's this line with regards to storage classes in C which seems to be used quite a bit in explanations on storage classes in C found online:
A storage class defines the scope (visibility) and life time of variables and/or functions within a C Program.
A storage class has no effect on the type of a variable, just how it's stored. Unfortunately, I can't find an exact list of storage classes in D, and people are quite liberal with the term storage class, using it even when it doesn't apply. Pretty much any attribute applied to a type save for access modifiers seems to get called a storage class, depending on who's talking. However, there are a few which are beyond a doubt storage classes:
enum (when used as a manifest constant)
extern
lazy
out
ref
scope
static
lazy, out, and ref can be used to modify function parameters and indicate how they're passed, whereas enum and static are used to indicate how the variables are stored (which is nowhere in the case of enum, since manifest constants are copy-pasted everywhere that they're used rather than being actual variables). extern affects linkage.
in is a hybrid, since it's a synonym for scope const, and while scope is a storage class, const is a type qualifier.
The online documentation also refers to auto and synchronized as storage classes, though I don't know on what basis. auto is like inout in that it's a placeholder (in its case a placeholder for a type rather than a type qualifier) and therefore indicates nothing about how a type is stored, so I wouldn't have thought that it would be a storage class. synchronized doesn't modify variables but rather classes.
__gshared is probably a storage class as well, though it's a bit funny, since it does more or less what shared (which is a type qualifier) does, but it's not part of the type.
Beyond that, I don't know. The fact that synchronized is listed as a storage class implies that some of the others (such as final) might be, but (like synchronized) they have nothing to do with how variables are stored or linked. So, I don't know how they could be considered storage classes.
I'll ask on the newsgroup though and see if I can get a more definitive list.
EDIT: It seems that there is no definitive, official list of storage classes in D. The term is used for almost any attribute used on a variable declaration which doesn't affect its type (i.e. not a type qualifier). It seems that Walter and Andrei tend to make a big point about the type qualifiers to underline which attributes actually affect the type of a variable, but the term storage class hasn't been given anywhere near the same level of importance and ends up being used informally rather than per any rigorous definition.

Related

Why is the global definition "const Date default_date(1970,1,1);" bad?

When reading the book Programming: Principles and Practices using C++, 2nd Edition I came along the following statement:
...what do you do if you really need a global variable (or constant)
with a complicated initializer? A plausible example would be that we
wanted a default value for a Date type we were providing for a library
supporting business transactions:
const Date default_date(1970,1,1); // the default date is January 1, 1970
How would we know that default_date was never used before it was
initialized? Basically, we can’t know, so we shouldn’t write that
definition...
What got me curious about this line of code is the implied idea of using a global variable before its definition. What did the author (Bjarne Stroupstrup) exactly mean by using a global variable before its initialization? Of course, one could have declared the variable somewhere else. But that scenario is not mentioned.
If there's another object declared in global scope, somewhere else, with a complex constructor, you have no practical means to specify the relative initialization order of these two objects in a portable manner. You can't expect, for either object, that the other object has been constructed, before it is referenced.
There's nothing inherently wrong with declaring global singleton objects, where they make sense, as long as it is fully understood that the relative initialization order of global objects in different translation units is not specified.

Is encapsulation violated, if I use a global variable in a class member function's definition?

I've been asked to explain what encapsulation is and I replied "bundling of data and functions that modify this data, is called encapsulation."
The answer was followed by another question—"So, by your definition if I modify a global variable from a member function of a class then the encapsulation is violated."
It made sense to answer YES.
I am not sure whether my explanation is wrong or following question is valid and my answer to it as YES is correct.
Can somebody help.
Quoting from wikipedia:
In programming languages, encapsulation is used to refer to one of two
related but distinct notions, and sometimes to the combination
thereof:
A language mechanism for restricting access to some of the object's components.
A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data
In my humble opinion the answer to the follow up question is subjective and it depends on the interpretation of the notion of encapsulation.
For example it's not a violation if the encapsulating data are limited to be the member variables of classes. A global variable that doesn't belong to an object is accessible by everyone and thus, accessing it via a member function doesn't consist any encapsulation violation.
On the other hand if you consider that encapsulation should be applied to your entire program then this global variable should have been bundled to an object and thus, raw access to it constitutes an encapsulation violation.
The bottom line is that the answer lies in the realms of theology, meaning that it depends on how encapsulation is interpreted by the different programming dogmas.
This depends on how global variable defined and accessed.
Imagine header file containing declaration, but not definitions of member functions, and corresponding implementation file containing class members implementation.
Now consider global variable defined in this header file as internal linkage one (static). Or placed in unnamed namespace. It is a global variable, but functionally it does not differ from private static class member.
It is smelly code, but, I say, that variable is encapsulated properly:

their representation is part of their definition as related to C++ concrete types?

In both of his books
The C++ Programming Language, 2013 (4th edition) and
A Tour of C++, 2013
Bjarne Stroustrup writes:
Types such as complex ... are called concrete types because
their representation is part of their definition.
What follows to some extent clarifies the above statement:
In that, they resemble built-in types. In contrast, an abstract type
is a type that completely insulates a user from implementation
details. To do that, we decouple the interface from the
representation and give up genuine local variables. Since we don’t
know anything about the representation of an abstract type (not even
its size), we must allocate objects on the free store and access them
through references or pointers.
Questions
In the phrase "...their representation is part of their definition."
What is the meaning of type representation? That is, the representation of what exactly: The object layout in memory? The private and public data that the type holds? Or something else?
What is the meaning of type definition?
Are these typical meanings of type representation and definition as related to C++?
I decided to do some more research and I checked other sources. First I looked through ISO/IEC 14882:2011 specifications that state requirements for implementations of the C++ programming language, then through other sources.
Ad question 1
I was not able to find in ISO specs anything like "type representation" or "representation of a type". Instead there are 2 terms related to objects:
The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T).
The value representation of an object is the set of bits that hold the value of type T. For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.
So it seems to me that the term type representation does not have any conventional meaning within the ISO standards.
Ok. Maybe it is something outside the ISO standards? Let's see what
Linux Standard Base C++ Specification 3.1 > Chapter 7. C++ Class Representations > 7.1. C++ Data Representation says:
An object file generated by the compilation process for a C++ program shall contain several closely related internal objects, or Class Components, to represent each C++ Class. Such objects are not a visible part of the source code. The following table describes these Class Components at a high level.
Table Class Components
Object.......................Contains
=----------------------------------------=
Class Data...................Class members
Virtual Table................Information needed to dispatch virtual functions,
access virtual base class subobjects and to access
the RTTI information
RTTI.........................Run-Time Type Information used by the typeid and
dynamic_cast operators, and exception handlers
Typeinfo Name................String representation of Class name
Construction Virtual Table...Information needed during construction and
destruction of Classes with non-trivial
inheritance relationships.
VTT..........................A table of virtual table pointers which holds the
addresses of construction and non-construction
virtual tables.
Ad question 2
I was again not able to find in ISO specs an explicit explanation of type definition.
Instead I found the following:
A declaration may introduce one or more names into a translation
unit... A class declaration introduces the class name into the
scope where it is declared...A declaration is a definition unless
[I removed things not directly related to the class declaration], ...
it is a class name declaration...
Here is a Microsoft interpretation of the same thing:
C++ Declarations - MSDN - Microsoft
A declaration introduces
one or more names into a program. Declarations can occur more than
once in a program...Declarations also serve as definitions, except
when the declaration:...;Is a class name declaration with no
following definition, such as class T;...
and
C++ Definitions - MSDN - Microsoft
A definition is a unique
specification of an object or variable, function, class, or
enumerator. Because definitions must be unique, a program can contain
only one definition for a given program element. There can be a
many-to-one correspondence between declarations and definitions.
There are two cases in which a program element can be declared and not defined: A function is declared but never referenced with a
function call or with an expression that takes the function's address.
A class is used only in a way that does not require its definition be
known.
Examples:
struct S; // declares, but not defines S
class T {}; // declares, and defines T
class P { int a;}; // declares, and defines P, P::a
Conclusions:
Candidate Answer N1:
proposed by Jonathan Wakely
(below is my understanding)
The phrase "Types such as complex ... are called concrete types because their representation is part of their definition" should be interpreted and understood in the following way:
● their(=type) definition is a technical c++ term whose meaning is conventional and can be found in c++ specs;
● their(=type) representation is (according to Jonathan Wakely) not a technical c++ term in this context, but its meaning can be easily figured out by anybody who understands English language well enough (and probably, it is my guess, has been previously exposed to the generous amount of c++ codes and texts). Type representation in this context means
"the properties that define what the type is and what it does", that is:
"for a concrete type: the type and layout of its members",
"for an abstract type: its member functions and their observable behavior"
● The whole phrase then (we are talking about the concrete classes) translates to:
"Types such as complex ... are called concrete types because the types and layouts of their members are part of their definition"
I think this interpretation makes sense, is understandable, and also agrees well with what follows it in the BS books.
Please correct me if something here is not ok**
QUESTIONS: in the phrase "...their representation is part of their definition." 1) What is the meaning of type representation? (that is, the representation of WHAT exactly: object layout in memory or private and public data that the type holds OR something else) 2) What is the meaning of type definition? 3) Are these typical meanings of type representation and definition as related to c++?
You're asking for the meaning of terms that Stroustrup doesn't use in the text you quoted!
He's not trying to define a formal specification of a term like "type representation" the way the C++ standard does, he's writing prose that is more informal. All the references to technical terms that you've dug up are misleading and not directly relevant.
(that is, the representation of WHAT exactly: object layout in memory or private and public data that the type holds OR something else)
Yes, both the things you mention. For a concrete type the properties that define what it is and what it does include the type and layout of its members. i.e. how it is represented in the source code.
For an abstract class, the properties that define what it is and what it does are its member functions and their observable behaviour. The details of how it produces that observable behaviour are not necessarily important, and sometimes aren't even visible in the source code because you actually use some concrete class defined in another piece of code and only use it through an abstract interface.
Edit: Judging from the comments you wrote below you apparently missed that I tried to give you an answer. What I wrote above refers to the properties that define what a type is and what it does. That is a "definition of a type".
If you had to write documentation for a C++ type for users, how would you define it?
For a concrete type you might describe the types of its members and so define some of its properties in terms of the properties of its members. e.g. "A std::complex<float> stores two float members, which represent the real and imaginary parts of the complex number." This tells you that std::complex<float> can only store complex numbers with the same precision as float, i.e. its precision is determined by the fact it is represented using two float members.
For an abstract class you would describe the behaviour of its member functions, which are likely to be virtual, so you describe it in terms of the interface it follows, not in terms of the details of its implementation.
But they are not formal terms, I think you are wrong to treat them as strict technical terms. He's just using the words with their usual English meaning.
You go looking out for a vegetable in dinner tonight. Wait.. a vegetable? The word vegetable defines something for sure but it carries no representation. Someone will surely ask you which vegetable. So a vegetable is an abstract concept.
So now you order some potatoes and onions. Well, they define some properties and represent themselves well enough so that you can locate them in the store. Potatoes and onions make up for concrete representation of a type with a well defined property and behavior.
Try writing two classes following this analogy. You may connect to what is meant by representation is part of their definition.
I stumbled over the same passage in the text, and it took me a while, but I believe I deduced from the text what is meant by representation and definition of a class.
Answer to question 1: The representation of a type are the data members. Those are the members of the type which store the information/state, as opposed to the methods/operations on them.
Answer to question 2: The definition is simply the code implementing the class. (like the definition of Vector below).
Rationale: See section 2.3.2 of the same book and pay close attention on the use of the word 'representation':
Having the data specified separately from the operations on it has advantages, such as the ability to use the data in arbitrary ways. However, a tighter connection between the representation and the operations is needed for a user-defined type to have all the properties expected of a "real type."
It seems that "representation" here now replaced "data".
Here, the representation of a Vector (the members elem and sz) [...]
elem and sz are precisely the data members of the Vector class defined in that section:
class Vector {
public:
Vector(int s) :elem{new double[s]}, sz{s} {} // construct a Vector
double& operator[](int i) { return elem[i]; } // element access: subscripting
int size() { return sz; }
private:
double* elem; // pointer to the elements
int sz; // the number of elements
};
Further Explanation:
For a concrete type, it is possible from the definition to tell how much memory must be allocated for the data members of an object of this type. When you declare a variable to be of that type somewhere in the source code of your program, the compiler will know its size in memory.
In the case of the class Vector defined above, the memory required for the data members of an instance of that class would be whatever memory is needed for an integer sz and a pointer to a double elem.
An abstract type on the other hand, may not specify data members in its definition, so that the memory required for an object of such a type would be unknown.
For more on abstract types see section 3.2.2 of the same book and note that the abstract class Container defined in that section has no data members (further supporting my answer to question 1).
With this understanding in mind, some of the exposition that follows the sentence in question where the words definition and representation are used makes sense.
I'll paraphrase:
since the representation is part of the definition of a concrete type, we can place an object of such a type on the stack, in statically allocated memory, and in other objects and we can refer to such objects directly and without the use of pointers or references, etc..
If we didn't know the size of the data members of an object, we wouldn't be able to do these things.
In response to question 3:
I do not know the answer to question number 3, but believe that as stated in previous answers, the terminology used here is informal and shouldn't be viewed as some sort of standard. This goes with the spirit of the part of the book this is written in which is only giving a brief high-level informal overview over C++ not assuming previous knowledge and thus avoiding jargon.

is static const string member variable always initialized before used?

In C++, if I want to define some non-local const string which can be used in different classes, functions, files, the approaches that I know are:
use define directives, e.g.
#define STR_VALUE "some_string_value"
const class member variable, e.g.
class Demo {
public:
static const std::string ConstStrVal;
};
// then in cpp
std::string Demo::ConstStrVal = "some_string_value";
const class member function, e.g.
class Demo{
public:
static const std::string GetValue(){return "some_string_value";}
};
Now what I am not clear is, if we use the 2nd approach, is the variable ConstStrVal always initialized to "some_string_value" before it is actually used by any code in any case? Im concerned about this because of the "static initialization order fiasco". If this issue is valid, why is everybody using the 2nd approach?
Which is the best approach, 2 or 3? I know that #define directives have no respect of scope, most people don't recommend it.
Thanks!
if we use the 2nd approach, is the variable ConstStrVal always initialized to "some_string_value" before it is actually used by any code in any case?
No
It depends on the value it's initialized to, and the order of initialization. ConstStrVal has a global constructor.
Consider adding another global object with a constructor:
static const std::string ConstStrVal2(ConstStrVal);
The order is not defined by the language, and ConstStrVal2's constructor may be called before ConstStrVal has been constructed.
The initialization order can vary for a number of reasons, but it's often specified by your toolchain. Altering the order of linked object files could (for example) change the order of your image's initialization and then the error would surface.
why is everybody using the 2nd approach?
many people use other approaches for very good reasons…
Which is the best approach, 2 or 3?
Number 3. You can also avoid multiple constructions like so:
class Demo {
public:
static const std::string& GetValue() {
// this is constructed exactly once, when the function is first called
static const std::string s("some_string_value");
return s;
}
};
caution: this is approach is still capable of the initialization problem seen in ConstStrVal2(ConstStrVal). however, you have more control over initialization order and it's an easier problem to solve portably when compared to objects with global constructors.
In general, I (and many others) prefer to use functions to return values rather than variables, because functions give greater flexibility for future enhancement. Remember that most of the time spent on a successful software project is maintaining and enhancing the code, not writing it in the first place. It's hard to predict if your constant today might not be a compile time constant tomorrow. Maybe it will be read from a configuration file some day.
So I recommend approach 3 because it does what you want today and leaves more flexibility for the future.
Avoid using the preprocessor with C++. Also, why would you have a string in a class, but need it in other classes? I would re-evaluate your class design to allow better encapsulation. If you absolutely need this global string then I would consider adding a globals.h/cpp module and then declare/define string there as:
const char* const kMyErrorMsg = "This is my error message!";
Don't use preprocessor directives in C++, unless you're trying to achieve a holy purpose that can't possibly be achieved any other way.
From the standard (3.6.2):
Objects with static storage duration (3.7.1) shall be zero-initialized
(8.5) before any other initialization takes place. A reference with
static storage duration and an object of POD type with static storage
duration can be initialized with a constant expression (5.19); this is
called constant initialization. Together, zero-initialization and
constant initialization are called static initialization; all other
initialization is dynamic initialization. Static initialization shall
be performed before any dynamic initialization takes place. Dynamic
initialization of an object is either ordered or unordered.
Definitions of explicitly specialized class template static data
members have ordered initialization. Other class template static data
members (i.e., implicitly or explicitly instantiated specializations)
have unordered initialization. Other objects defined in namespace
scope have ordered initialization. Objects defined within a single
translation unit and with ordered initialization shall be initialized
in the order of their definitions in the translation unit. The order
of initialization is unspecified for objects with unordered
initialization and for objects defined in different translation units.
So, the fate of 2 depends on whether your variable is static initialised or dynamic initialised. For instance, in your concrete example, if you use const char * Demo::ConstStrVal = "some_string_value"; (better yet const char Demo::ConstStrVal[] if the value will stay constant in the program) you can be sure that it will be initialised no matter what. With a std::string, you can't be sure since it's not a POD type (I'm not dead sure on this one, but fairly sure).
3rd method allows you to be sure and the method in Justin's answer makes sure that there are no unnecessary constructions. Though keep in mind that the static method has a hidden overhead of checking whether or not the variable is already initialised on every call. If you're returning a simple constant, just returning your value is definitely faster since the function will probably be inlined.
All of that said, try to write your programs so as not to rely on static initialisation. Static variables are best regarded as a convenience, they aren't convenient any more when you have to juggle their initialisation orders.

Difference between static in C and static in C++??

What is the difference between the static keyword in C and C++?
The static keyword serves the same purposes in C and C++.
When used at file level (outside of a function), it sets the visibility of the item it's applied to. Static items are not visible outside of their compilation unit (e.g., to the linker). Their duration is the same as the duration of the program.
These file-level items (functions and data) should be static unless there's a specific need to access them from outside (and there's almost never a need to give direct access to data since that breaks the central tenet of encapsulation).
If (as your comment to the question indicates) this is the only use of static you're concerned with then, no, there is no difference between C and C++.
When used within a function, it sets the duration of the item. Again, the duration is the same as the program and the item continues to exist between invocations of that function.
It does not affect the visibility of that item since it's visible only within the function. An example is a random number generator that needs to keep its seed value between invocations but doesn't want that value visible to other functions.
C++ has one more use, static within a class. When used there, it becomes a single class variable that's common across all objects of that class. One classic example is to store the number of objects that have been instantiated for a given class.
As others have pointed out, the use of file-level static has been deprecated in favour of unnamed namespaces. However, I believe it'll be a cold day in a certain warm place before it's actually removed from the language - there's just too much code using it at the moment. And ISO C have only just gotten around to removing gets() despite the amount of time we've all known it was a dangerous function.
And even though it's deprecated, that doesn't change its semantics now.
The use of static at the file scope to restrict access to the current translation unit is deprecated in C++, but still acceptable in C.
Instead, use an unnamed namespace
namespace
{
int file_scope_x;
}
Variables declared this way are only available within the file, just as if they were declared static.
The main reason for the deprecation is to remove one of the several overloaded meanings of the static keyword.
Originally, it meant that the variable, such as in a function, would be given storage for the lifetime of the program in an area for such variables, and not stored on the stack as is usual for function local variables.
Then the keyword was overloaded to apply to file scope linkage. It's not desirable to make up new keywords as needed, because they might break existing code. So this one was used again with a different meaning without causing conflicts, because a variable declared as static can't be both inside a function and at the top level, and functions didn't have the modifier before. (The storage connotation is totally lost when referring to functions, as they are not stored anywhere.)
When classes came along in C++ (and in Java and C#) the keyword was used yet again, but the meaning is at least closer to the original intention. Variables declared this way are stored in a global area, as opposed to on the stack as for function variables, or on the heap as for object members. Because variables cannot be both at the top level and inside a class definition, extra meaning can be unambiguously attached to class variables. They can only be referenced via the class name or from within an object of that class.
It has the same meaning in both languages.
But C++ adds classes. In the context of a class (and thus a struct) it has the extra meaning of making the method/variable class members rather members of the object.
class Plop
{
static int x; // This is a member of the class not an instance.
public:
static int getX() // method is a member of the class.
{
return x;
}
};
int Plop::x = 5;
Note that the use of static to mean "file scope" (aka namespace scope) is only deoprecated by the C++ Standard for objects, not for functions. In other words,:
// foo.cpp
static int x = 0; // deprecated
static int f() { return 1; } // not deprecated
To quote Annex D of the Standard:
The use of the static keyword is
deprecated when declaring objects in
namespace scope.
You can not declare a static variable inside structure in C... But allowed in Cpp with the help of scope resolution operator.
Also in Cpp static function can access only static variables but in C static function can have static and non static variables...😊