I thought that every declaration is definition because there was the following quote from standard:
A declaration is a definition unless %restrictions%.
But my assumption is not true. Actually, applying ODR we have that the following program
class A;
class A;
int main(){ }
is ill-formed. But it is not true. I can't to find part of standard which permit to redeclare class type in the declarative region.
Yes, "a declaration is a definition unless %restrictions%" is true. Have you read the restrictions? One of them is:
it is a class name declaration
So class A; is not a definition because it is covered by one of the restrictions.
Just to clarify, quoting C++11, [basic.def]§2
Your quote (from C++11 3.1/2) answers the general question: "unless %restrictions%" means that not every declaration is a definition. It's only a definition if none of those restrictions apply.
If you read those restrictions, you'll find
it is a class name declaration
which answers your specific question. class A; is a class name declaration, but not a definition.
I can't to find part of standard which permit to redeclare class type in the declarative region.
In general, you can declare an entity multiple times in the same declarative region, per C++11 3.3.1/4
Given a set of declarations in a single declarative region, each of which specifies the same unqualified name, they shall all refer to the same entity, or [other cases not relevant here]
The paragraph § 3.1.2 states that
A declaration is a definition unless it declares a function without
specifying the function’s body (8.4), it contains the extern specifier
(7.1.1) or a linkage-specification 25 (7.5) and neither an initializer
nor a function- body, it declares a static data member in a class
definition (9.2, 9.4), it is a class name declaration (9.1), it is an
opaque-enum-declaration (7.2), it is a template-parameter (14.1), it
is a parameter-declaration (8.3.5) in a function declarator that is
not the declarator of a function-definition, or it is a typedef
declaration (7.1.3), an alias-declaration (7.1.3), a using-declaration
(7.3.3), a static_assert-declaration (Clause 7), an attribute-
declaration (Clause 7), an empty-declaration (Clause 7), or a
using-directive (7.3.4).
Here
class A;
class A;
int main(){ }
it is a class name declaration.
In a statement
A declaration is a definition unless %restrictions%.
the %restrictions%. part is important.
I thought that every declaration is definition
Let's prove that this is not true by a contradiction. So assume this is true. Then because we can have many redeclaration and every of this declarations is definition - we can have many redefinitions, right? But C++ Standard n3337 § 3.2/1 says
No translation unit shall contain more than one definition of any
variable, function, class type, enumeration type, or template.
what contradicts our assumption and thus this is not true that every declaration is definition.
Consider the case of:
Header1.h:
class A;
void function1(A * a);
Header2.h:
class A;
void function2(A * a);
main.cpp
#include "Header1.h"
#include "Header2.h"
#include "A.h" // header file defining A
int main()
{
}
what this really looks like to the compiler is:
class A;
void function1(A * a);
class A;
void function2(A * a);
class A { /* definition from A.h */ };
int main()
{
}
Related
After reading the question, I know the differences between declaration and definition. So does it mean definition equals declaration plus initialization?
Declaration
Declaration, generally, refers to the introduction of a new name in the program. For example, you can declare a new function by describing it's "signature":
void xyz();
or declare an incomplete type:
class klass;
struct ztruct;
and last but not least, to declare an object:
int x;
It is described, in the C++ standard, at §3.1/1 as:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
Definition
A definition is a definition of a previously declared name (or it can be both definition and declaration). For example:
int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };
Specifically the C++ standard defines it, at §3.1/1, as:
A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function- body, it declares a static data member in a class definition (9.2, 9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), it is a template-parameter (14.1), it is a parameter-declaration (8.3.5) in a function declarator that is not the declarator of a function-definition, or it is a typedef declaration (7.1.3), an alias-declaration (7.1.3), a using-declaration (7.3.3), a static_assert-declaration (Clause 7), an attribute- declaration (Clause 7), an empty-declaration (Clause 7), or a using-directive (7.3.4).
Initialization
Initialization refers to the "assignment" of a value, at construction time. For a generic object of type T, it's often in the form:
T x = i;
but in C++ it can be:
T x(i);
or even:
T x {i};
with C++11.
Conclusion
So does it mean definition equals declaration plus initialization?
It depends. On what you are talking about. If you are talking about an object, for example:
int x;
This is a definition without initialization. The following, instead, is a definition with initialization:
int x = 0;
In certain context, it doesn't make sense to talk about "initialization", "definition" and "declaration". If you are talking about a function, for example, initialization does not mean much.
So, the answer is no: definition does not automatically mean declaration plus initialization.
Declaration says "this thing exists somewhere":
int foo(); // function
extern int bar; // variable
struct T
{
static int baz; // static member variable
};
Definition says "this thing exists here; make memory for it":
int foo() {} // function
int bar; // variable
int T::baz; // static member variable
Initialisation is optional at the point of definition for objects, and says "here is the initial value for this thing":
int bar = 0; // variable
int T::baz = 42; // static member variable
Sometimes it's possible at the point of declaration instead:
struct T
{
static int baz = 42;
};
…but that's getting into more complex features.
For C, at least, per C11 6.7.5:
A declaration specifies the interpretation and attributes of a set of
identifiers. A definition of an identifier is a declaration for that
identifier that:
for an object, causes storage to be reserved for that object;
for a function, includes the function body;
for an enumeration constant, is the (only) declaration of the identifier;
for a typedef name, is the first (or only) declaration of the identifier.
Per C11 6.7.9.8-10:
An initializer specifies the initial value stored in an object ... if
an object that has automatic storage is not initialized explicitly,
its value is indeterminate.
So, broadly speaking, a declaration introduces an identifier and provides information about it. For a variable, a definition is a declaration which allocates storage for that variable.
Initialization is the specification of the initial value to be stored in an object, which is not necessarily the same as the first time you explicitly assign a value to it. A variable has a value when you define it, whether or not you explicitly give it a value. If you don't explicitly give it a value, and the variable has automatic storage, it will have an initial value, but that value will be indeterminate. If it has static storage, it will be initialized implicitly depending on the type (e.g. pointer types get initialized to null pointers, arithmetic types get initialized to zero, and so on).
So, if you define an automatic variable without specifying an initial value for it, such as:
int myfunc(void) {
int myvar;
...
You are defining it (and therefore also declaring it, since definitions are declarations), but not initializing it. Therefore, definition does not equal declaration plus initialization.
"So does it mean definition equals declaration plus initialization."
Not necessarily, your declaration might be without any variable being initialized like:
void helloWorld(); //declaration or Prototype.
void helloWorld()
{
std::cout << "Hello World\n";
}
struct A{
virtual void fun() = 0;
};
extern A a; //#1
void foo(A); //#2
int main(){}
The declarations at #1 and #2 are both complained as invalid declarations by GCC and Clang. The result is here.
However according to the current draft, it does not explicitly forbid this usage. What it states are just in the following
[basic.def#5]
In the definition of an object, the type of that object shall not be an incomplete type ([basic.types]), an abstract class type, or a (possibly multi-dimensional) array thereof.
In my example, the object a at #1 and the unnamed parameter at #2 are merely declarations rather than definitions, as per
[basic.def#2]
Each entity declared by a declaration is also defined by that declaration unless:
it contains the extern specifier or a linkage-specification19 ([dcl.link]) and neither an initializer nor a function-body,
it is a parameter-declaration in a function declarator that is not the declarator of a function-definition
The other place limits the usage of abstract class type related to this example is section [dcl.fct.def]
The type of a parameter or the return type for a function definition shall not be a (possibly cv-qualified) class type that is incomplete or abstract within the function body unless the function is deleted
In other words, it does not limit the usage of abstract class type in a function declaration that is not a definition.
So, according to the behavior of the compilers, Could it say that, in the declaration of an object, the type of that object shall not be an abstract class type? If I miss some normative rule that limits the usage of abstract class type, please point it out.
I believe the new wording for [namespace.memdef]/1 tries to explain the conflict between the two declarations using M::g; and void g(); in namespace X, but I fail to understand the relationship between this new wording and the alluded conflict.
A declaration in a namespace N (excluding declarations in nested
scopes) whose declarator-id is an unqualified-id ([dcl.meaning]),
whose class-head-name (Clause [class]) or enum-head-name
([dcl.enum]) is an identifier, or whose elaborated-type-specifier
is of the form class-key attribute-specifier-seqopt
identifier ([dcl.type.elab]), or that is an opaque-enum-declaration, declares (or redeclares) its unqualified-id or identifier as a member of N. [ Note: An explicit instantiation ([temp.explicit]) or explicit specialization
([temp.expl.spec]) of a template does not introduce a name and thus
may be declared using an unqualified-id in a member of the enclosing
namespace set, if the primary template is declared in an inline
namespace. — end note ] [ Example:
namespace X {
void f() { /* ... */ } // OK: introduces X::f()
namespace M {
void g(); // OK: introduces X::M::g()
}
using M::g;
void g(); // error: conflicts with X::M::g()
}
— end example ]
Even when I look at the DR 1838 which probably gave origin to the change in this paragraph, I have some problems understanding the following sentence (emphasis is mine):
The Standard is not clear about what happens when an entity is
declared but not defined in an inner namespace and declared via a
using-declaration in an outer namespace, and a definition of an entity with that name as an unqualified-id appears in the outer
namespace. Is this a legitimate definition of the inner-namespace
entity, as it would be if the definition used a qualified-id, or is
the definition a member of the outer namespace and thus in conflict
with the using-declaration? There is implementation divergence on
the treatment of such definitions.
The example that follows this sentence is exactly the same as the one in the paragraph [namespace.memdef]/1. I highlighted the word definition above, as there is no definition for the function X::g() in the alluded Example. What am I missing?
After reading the question, I know the differences between declaration and definition. So does it mean definition equals declaration plus initialization?
Declaration
Declaration, generally, refers to the introduction of a new name in the program. For example, you can declare a new function by describing it's "signature":
void xyz();
or declare an incomplete type:
class klass;
struct ztruct;
and last but not least, to declare an object:
int x;
It is described, in the C++ standard, at §3.1/1 as:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
Definition
A definition is a definition of a previously declared name (or it can be both definition and declaration). For example:
int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };
Specifically the C++ standard defines it, at §3.1/1, as:
A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function- body, it declares a static data member in a class definition (9.2, 9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), it is a template-parameter (14.1), it is a parameter-declaration (8.3.5) in a function declarator that is not the declarator of a function-definition, or it is a typedef declaration (7.1.3), an alias-declaration (7.1.3), a using-declaration (7.3.3), a static_assert-declaration (Clause 7), an attribute- declaration (Clause 7), an empty-declaration (Clause 7), or a using-directive (7.3.4).
Initialization
Initialization refers to the "assignment" of a value, at construction time. For a generic object of type T, it's often in the form:
T x = i;
but in C++ it can be:
T x(i);
or even:
T x {i};
with C++11.
Conclusion
So does it mean definition equals declaration plus initialization?
It depends. On what you are talking about. If you are talking about an object, for example:
int x;
This is a definition without initialization. The following, instead, is a definition with initialization:
int x = 0;
In certain context, it doesn't make sense to talk about "initialization", "definition" and "declaration". If you are talking about a function, for example, initialization does not mean much.
So, the answer is no: definition does not automatically mean declaration plus initialization.
Declaration says "this thing exists somewhere":
int foo(); // function
extern int bar; // variable
struct T
{
static int baz; // static member variable
};
Definition says "this thing exists here; make memory for it":
int foo() {} // function
int bar; // variable
int T::baz; // static member variable
Initialisation is optional at the point of definition for objects, and says "here is the initial value for this thing":
int bar = 0; // variable
int T::baz = 42; // static member variable
Sometimes it's possible at the point of declaration instead:
struct T
{
static int baz = 42;
};
…but that's getting into more complex features.
For C, at least, per C11 6.7.5:
A declaration specifies the interpretation and attributes of a set of
identifiers. A definition of an identifier is a declaration for that
identifier that:
for an object, causes storage to be reserved for that object;
for a function, includes the function body;
for an enumeration constant, is the (only) declaration of the identifier;
for a typedef name, is the first (or only) declaration of the identifier.
Per C11 6.7.9.8-10:
An initializer specifies the initial value stored in an object ... if
an object that has automatic storage is not initialized explicitly,
its value is indeterminate.
So, broadly speaking, a declaration introduces an identifier and provides information about it. For a variable, a definition is a declaration which allocates storage for that variable.
Initialization is the specification of the initial value to be stored in an object, which is not necessarily the same as the first time you explicitly assign a value to it. A variable has a value when you define it, whether or not you explicitly give it a value. If you don't explicitly give it a value, and the variable has automatic storage, it will have an initial value, but that value will be indeterminate. If it has static storage, it will be initialized implicitly depending on the type (e.g. pointer types get initialized to null pointers, arithmetic types get initialized to zero, and so on).
So, if you define an automatic variable without specifying an initial value for it, such as:
int myfunc(void) {
int myvar;
...
You are defining it (and therefore also declaring it, since definitions are declarations), but not initializing it. Therefore, definition does not equal declaration plus initialization.
"So does it mean definition equals declaration plus initialization."
Not necessarily, your declaration might be without any variable being initialized like:
void helloWorld(); //declaration or Prototype.
void helloWorld()
{
std::cout << "Hello World\n";
}
After reading the question, I know the differences between declaration and definition. So does it mean definition equals declaration plus initialization?
Declaration
Declaration, generally, refers to the introduction of a new name in the program. For example, you can declare a new function by describing it's "signature":
void xyz();
or declare an incomplete type:
class klass;
struct ztruct;
and last but not least, to declare an object:
int x;
It is described, in the C++ standard, at §3.1/1 as:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
Definition
A definition is a definition of a previously declared name (or it can be both definition and declaration). For example:
int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };
Specifically the C++ standard defines it, at §3.1/1, as:
A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function- body, it declares a static data member in a class definition (9.2, 9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), it is a template-parameter (14.1), it is a parameter-declaration (8.3.5) in a function declarator that is not the declarator of a function-definition, or it is a typedef declaration (7.1.3), an alias-declaration (7.1.3), a using-declaration (7.3.3), a static_assert-declaration (Clause 7), an attribute- declaration (Clause 7), an empty-declaration (Clause 7), or a using-directive (7.3.4).
Initialization
Initialization refers to the "assignment" of a value, at construction time. For a generic object of type T, it's often in the form:
T x = i;
but in C++ it can be:
T x(i);
or even:
T x {i};
with C++11.
Conclusion
So does it mean definition equals declaration plus initialization?
It depends. On what you are talking about. If you are talking about an object, for example:
int x;
This is a definition without initialization. The following, instead, is a definition with initialization:
int x = 0;
In certain context, it doesn't make sense to talk about "initialization", "definition" and "declaration". If you are talking about a function, for example, initialization does not mean much.
So, the answer is no: definition does not automatically mean declaration plus initialization.
Declaration says "this thing exists somewhere":
int foo(); // function
extern int bar; // variable
struct T
{
static int baz; // static member variable
};
Definition says "this thing exists here; make memory for it":
int foo() {} // function
int bar; // variable
int T::baz; // static member variable
Initialisation is optional at the point of definition for objects, and says "here is the initial value for this thing":
int bar = 0; // variable
int T::baz = 42; // static member variable
Sometimes it's possible at the point of declaration instead:
struct T
{
static int baz = 42;
};
…but that's getting into more complex features.
For C, at least, per C11 6.7.5:
A declaration specifies the interpretation and attributes of a set of
identifiers. A definition of an identifier is a declaration for that
identifier that:
for an object, causes storage to be reserved for that object;
for a function, includes the function body;
for an enumeration constant, is the (only) declaration of the identifier;
for a typedef name, is the first (or only) declaration of the identifier.
Per C11 6.7.9.8-10:
An initializer specifies the initial value stored in an object ... if
an object that has automatic storage is not initialized explicitly,
its value is indeterminate.
So, broadly speaking, a declaration introduces an identifier and provides information about it. For a variable, a definition is a declaration which allocates storage for that variable.
Initialization is the specification of the initial value to be stored in an object, which is not necessarily the same as the first time you explicitly assign a value to it. A variable has a value when you define it, whether or not you explicitly give it a value. If you don't explicitly give it a value, and the variable has automatic storage, it will have an initial value, but that value will be indeterminate. If it has static storage, it will be initialized implicitly depending on the type (e.g. pointer types get initialized to null pointers, arithmetic types get initialized to zero, and so on).
So, if you define an automatic variable without specifying an initial value for it, such as:
int myfunc(void) {
int myvar;
...
You are defining it (and therefore also declaring it, since definitions are declarations), but not initializing it. Therefore, definition does not equal declaration plus initialization.
"So does it mean definition equals declaration plus initialization."
Not necessarily, your declaration might be without any variable being initialized like:
void helloWorld(); //declaration or Prototype.
void helloWorld()
{
std::cout << "Hello World\n";
}