This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 6.2.3 - The source code used to implement an entity shall appear only once
[basic.def.odr] Undefined 6.6; NDR 4
Category: Required
Analysis: Decidable, System
Amplification
For the purposes of this rule, an entity is a variable, type, function, or template thereof.
Note: multiple different specializations for the same primary template and multiple overloads for a function
with the same name but with different signatures are different entities.
This rule requires that the source code used to implement an entity shall appear only once within a project. If the entity is
inline, it can be implemented within a header file [1]; it is permitted to include such a header file [1] in multiple
translation units.
Additionally, explicit specializations of templates shall either be implemented in the same file as the primary template, or in a
file where one of the fully specialized arguments is defined.
Note: an entity may have no implementation — for example, an incomplete type does not need a definition when it is used
as a tag.
Rationale
Non-inline entities shall only be defined once in a program. Inline entities can be defined once for each translation
unit, but the definitions shall be identical. This principle is known as the one-definition rule.
Requiring that the source code for the definition of any entity appears only once reduces the risk of violating the one-definition
rule and makes the code simpler.
The declaration of a template’s explicit specialization must be visible when it matches the arguments of the template that is being
instantiated, otherwise, an implicit specialization will be generated, violating the one-definition rule. Implementing an
explicit specialization in the same file as the primary template or the argument for which it is specialized ensures that this
constraint is satisfied.
Example
// file1.h
inline int16_t i = 10;
// file2.h
inline int16_t i = 10; // Non-compliant - two definitions of i
The following example demonstrates inconsistent definitions of b:
// file1.cpp
int16_t b; // Non-compliant - ill-formed (see file2.cpp)
// file2.cpp
int32_t b; // Non-compliant - ill-formed (see file1.cpp)
In the following example, the full template specialization within a different file results in a violation of the one-definition rule
(which is not the case for the template specialization A< D >, as that is within the file that defines D):
// a.h - #include guard omitted for brevity
template< typename T >
class A {};
// b.h
#include "a.h"
A< int32_t > const a1 {};
// c.h
#include "a.h"
template<>
class A< int32_t > {}; // Non-compliant
// d.h
#include "a.h"
class D {};
template<>
class A< D > {}; // Compliant
// main.cpp
#include "b.h"
#include "c.h" // ODR violation
#include "d.h"
A< D > const a2 {}; // OK - requires inclusion of d.h
In the following example, the partial template specialization within a different file results in a violation of the one-definition
rule:
// wrap.h
template< typename V >
struct wrap
{
V value;
};
// wrap_ptr.h
#include "wrap.h"
template< typename V >
struct wrap< V * > {} // Non-compliant - should be in wrap.h
// w.cpp
#include "wrap.h" // No specialization visible
wrap< char * > a_wrap; // ODR violation - see wp.cpp
// wp.cpp
#include "wrap_ptr.h" // Specialization visible
wrap< char * > b_wrap; // ODR violation - see w.cpp
Glossary
[1] Header file
A header file is considered to be any file that is included during preprocessing (for example via the #include directive),
regardless of its name or suffix.
Copyright The MISRA Consortium Limited © 2023