Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

non-static data members and one definition rule

Premise

In accordance with the One Definition Rule, as stated in the C++14 Standard, I can have a definition of the same class in each translation unit as long as I follow the rules in 3.2.6. This means allows the following program to be legal:

//a_1.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicity inlined 
};

//a_2.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicity inlined 
};

If I try to define b or foo(), I am, however, limited to a single definition across the entire program, which I believe is due to the statement in 3.2.4:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

For this reason, the following program is ill-formed:

//a_1.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicity inlined 
};
int A::b;

//a_2.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicitly inlined 
};
int A::b;

The same if I tried to define foo() in both source files.

I can, however, have multiple definitions of boo() (one per translation unit) as this is not prohibited by 3.2.4 and is, actually, explicitly allowed by 3.2.6:

There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit.

To be fair, 3.2.6 qualifies the statement above adding a few requirement, among which the entity (in our case boo()) must be defined with the same sequence of tokens in each translation unit.

Question

What about the non-static data member a? Multiple definitions of a are obviously allowed (otherwise the program at the top of my question would not compile), but this would seem to be prohibited by 3.2.4 and not condoned by 3.2.6. Is this just a detail not strictly specified in the standard or am I missing something?

Edit

For those who have indicated to me that a is not defined, but is just declared, please consider this example, taken straight from the C++14 Standard, 3.2.2:

struct X { // defines X
    int x; // defines non-static data member x
    static int y; // declares static data member y
    X(): x(0) { } // defines a constructor of X
};

Please not that the comments to the code above are not mine, rather copied as well directly from the standard.

like image 557
StrG30 Avatar asked Oct 29 '22 16:10

StrG30


1 Answers

[basic.def.odr]/1:

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

Variable is defined by [basic]/6:

A variable is introduced by the declaration of a reference other than a non-static data member or of an object.

Therefore, as a non-static data member is not a variable, function, class, enumeration, or template, the one definition rule simply doesn't apply to non-static data members.

like image 138
Oktalist Avatar answered Nov 09 '22 15:11

Oktalist