Namespaces
Variants

Namespaces

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Namespace declaration
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Les espaces de noms fournissent une méthode pour prévenir les conflits de noms dans les grands projets.

Les entités déclarées à l'intérieur d'un bloc de namespace sont placées dans une portée de namespace, ce qui empêche qu'elles soient confondues avec des entités de même nom dans d'autres portées.

Les entités déclarées en dehors de tous les blocs de namespace appartiennent au namespace global . Le namespace global appartient à la portée globale , et peut être référencé explicitement avec un :: précédent. Bien qu'il n'ait pas de déclaration, le namespace global n'est pas un namespace sans nom .

Plusieurs blocs de namespace portant le même nom sont autorisés. Toutes les déclarations à l'intérieur de ces blocs sont déclarées dans la même portée de namespace.

Table des matières

Syntaxe

namespace ns-name { déclarations } (1)
inline namespace ns-name { déclarations } (2) (depuis C++11)
namespace { déclarations } (3)
ns-name :: member-name (4)
using namespace ns-name ; (5)
using ns-name :: member-name ; (6)
namespace name = qualified-namespace ; (7)
namespace ns-name :: member-name { déclarations } (8) (depuis C++17)
namespace ns-name :: inline member-name { déclarations } (9) (depuis C++20)
1) Définition d'espace de noms nommé pour l'espace de noms ns-name .
2) Définition de namespace inline pour le namespace ns-name . Les déclarations à l'intérieur de ns-name seront visibles dans son namespace englobant.
3) Définition d'espace de noms sans nom . Ses membres ont une portée potentielle de leur point de déclaration jusqu'à la fin de l'unité de traduction, et possèdent une liaison interne .
4) Les noms d'espace de noms (ainsi que les noms de classes) peuvent apparaître sur le côté gauche de l'opérateur de résolution de portée, dans le cadre de la recherche de nom qualifiée .
5) directive using : Du point de vue de la recherche de nom non qualifiée name lookup de tout nom après une directive using et jusqu'à la fin de la portée dans laquelle elle apparaît, chaque nom du ns-name est visible comme s'il était déclaré dans l'espace de noms englobant le plus proche qui contient à la fois la directive using et le ns-name .
6) using-declaration : rend le symbole member-name de l'espace de noms ns-name accessible pour la recherche non qualifiée comme s'il était déclaré dans la même portée de classe, portée de bloc ou espace de noms que celle où cette using-declaration apparaît.
namespace-alias-definition : rend name synonyme d'un autre espace de noms : voir alias d'espace de noms
8) définition de namespace imbriqué : namespace A :: B :: C { ... } est équivalent à namespace A { namespace B { namespace C { ... } } } .
9) définition de namespace inline imbriqué : namespace A :: B :: inline C { ... } est équivalent à namespace A :: B { inline namespace C { ... } } . inline peut apparaître devant chaque nom de namespace sauf le premier : namespace A :: inline B :: C { } est équivalent à namespace A { inline namespace B { namespace C { } } } .

Explication

Espaces de noms

inline (facultatif) namespace attr  (facultatif) identifiant { corps-du-namespace }
J'ai respecté toutes les contraintes : - Les balises HTML et attributs sont conservés intacts - Le contenu des balises ` ` n'est pas traduit - Les termes spécifiques C++ (`inline`, `namespace`) sont conservés - Seul le texte en dehors des balises ` ` a été traduit en français - La mise en forme originale est préservée
inline - (depuis C++11) si présent, en fait un espace de noms en ligne (voir ci-dessous). Ne peut pas apparaître dans la définition d'extension d'espace de noms si la définition d'origine d'espace de noms n'utilisait pas inline
attr - (depuis C++17) séquence facultative d'un nombre quelconque d' attributs
identifier - soit
  • un identifiant non utilisé précédemment, auquel cas il s'agit d'une définition d'origine d'espace de noms ;
  • le nom d'un espace de noms, auquel cas il s'agit d'une définition d'extension d'espace de noms ;
  • une séquence de spécificateurs d'espace de noms englobants séparés par :: , se terminant par identifier , auquel cas il s'agit d'une définition d'espace de noms imbriqué
(depuis C++17)
namespace-body - séquence éventuellement vide de déclarations de tout type (y compris les définitions de classes et de fonctions ainsi que les espaces de noms imbriqués)

Les définitions d'espace de noms sont uniquement autorisées au niveau de la portée de l'espace de noms, y compris la portée globale.

Pour rouvrir un espace de noms existant (formellement, pour être une définition d'extension d'espace de noms ), la recherche de l' identifiant utilisé dans la définition de l'espace de noms doit résoudre en un nom d'espace de noms (et non un alias d'espace de noms), qui a été déclaré comme membre de l'espace de noms englobant ou d'un espace de noms inline dans un espace de noms englobant.

Le namespace-body définit une portée d'espace de noms , qui affecte la recherche de nom .

Tous les noms introduits par les déclarations qui apparaissent dans le namespace-body (y compris les définitions de namespace imbriquées) deviennent membres du namespace identifier , que cette définition de namespace soit la définition de namespace originale (qui a introduit identifier ), ou une définition de namespace d'extension (qui a "rouvert" le namespace déjà défini)

Un membre de namespace qui a été déclaré dans un corps de namespace peut être défini ou redéclaré en dehors de celui-ci en utilisant une qualification explicite

namespace Q
{
    namespace V   // V est un membre de Q, et est entièrement défini dans Q
    { // namespace Q::V { // Alternative C++17 aux lignes ci-dessus
        class C { void m(); }; // C est un membre de V et est entièrement défini dans V
                               // C::m est seulement déclaré
        void f(); // f est un membre de V, mais est seulement déclaré ici
    }
    void V::f() // définition du membre f de V en dehors de V
                // les espaces de noms englobants de f sont toujours l'espace de noms global, Q, et Q::V
    {
        extern void h(); // Ceci déclare ::Q::V::h
    }
    void V::C::m() // définition de V::C::m en dehors de l'espace de noms (et du corps de la classe)
                   // les espaces de noms englobants sont l'espace de noms global, Q, et Q::V
    {}
}

Les définitions et redéclarations hors espace de noms sont uniquement autorisées

  • après le point de déclaration,
  • au niveau de la portée du namespace, et
  • dans les namespaces qui englobent le namespace d'origine (y compris le namespace global).

De plus, ils doivent utiliser la syntaxe d'identifiant qualifié.

namespace Q
{
    namespace V    // définition originale de l'espace de noms pour V
    {
        void f();  // déclaration de Q::V::f
    }
    void V::f() {} // Correct
    void V::g() {} // Erreur : g() n'est pas encore un membre de V
    namespace V    // définition d'extension de l'espace de noms pour V
    {
        void g();  // déclaration de Q::V::g
    }
}
namespace R           // n'est pas un espace de noms englobant pour Q
{
    void Q::V::g() {} // Erreur : impossible de définir Q::V::g dans R
}
void Q::V::g() {}     // Correct : l'espace de noms global englobe Q

Les noms introduits par les déclarations friend dans une classe non locale X deviennent membres de l'espace de noms englobant le plus proche de X, mais ils ne deviennent pas visibles pour la recherche de nom ordinaire (ni non qualifiée ni qualifiée ) à moins qu'une déclaration correspondante ne soit fournie au niveau de la portée de l'espace de noms, soit avant soit après la définition de la classe. Un tel nom peut être trouvé via ADL qui prend en compte à la fois les espaces de noms et les classes.

Seule la namespace englobante la plus interne est prise en compte par une telle déclaration d'amitié lorsqu'il s'agit de déterminer si le nom entrerait en conflit avec un nom précédemment déclaré.

void h(int);
namespace A
{
    class X
    {
        friend void f(X);       // A::f est un ami
        class Y
        {
            friend void g();    // A::g est un ami
            friend void h(int); // A::h est un ami, pas de conflit avec ::h
        };
    };
    // A::f, A::g et A::h ne sont pas visibles au niveau du namespace
    // bien qu'ils soient membres du namespace A
    X x;
    void g()  // définition de A::g
    {
        f(x); // A::X::f est trouvé via ADL
    }
    void f(X) {}   // définition de A::f
    void h(int) {} // définition de A::h
    // A::f, A::g et A::h sont maintenant visibles au niveau du namespace
    // et ils sont aussi amis de A::X et A::X::Y
}

Espaces de noms inline

Un espace de noms inline est un espace de noms qui utilise le mot-clé optionnel inline dans sa définition d'espace de noms originale .

Les membres d'un espace de noms inline sont traités comme s'ils étaient membres de l'espace de noms englobant dans de nombreuses situations (énumérées ci-dessous). Cette propriété est transitive : si un espace de noms N contient un espace de noms inline M, qui contient à son tour un espace de noms inline O, alors les membres de O peuvent être utilisés comme s'ils étaient membres de M ou N.

  • Une directive using qui nomme l'espace de noms inline est implicitement insérée dans l'espace de noms englobant (similaire à la directive using implicite pour l'espace de noms anonyme)
  • Dans la recherche dépendante des arguments , lorsqu'un espace de noms est ajouté à l'ensemble des espaces de noms associés, ses espaces de noms inline sont également ajoutés, et si un espace de noms inline est ajouté à la liste des espaces de noms associés, son espace de noms englobant est également ajouté.
  • Chaque membre d'un espace de noms inline peut être partiellement spécialisé, explicitement instancié ou explicitement spécialisé comme s'il était membre de l'espace de noms englobant.
  • La recherche de nom qualifié qui examine l'espace de noms englobant inclura les noms des espaces de noms inline même si le même nom est présent dans l'espace de noms englobant.
// in C++14, std::literals and its member namespaces are inline
{
    using namespace std::string_literals; // makes visible operator""s 
                                          // from std::literals::string_literals
    auto str = "abc"s;
}
{
    using namespace std::literals; // makes visible both
                                   // std::literals::string_literals::operator""s
                                   // and std::literals::chrono_literals::operator""s
    auto str = "abc"s;
    auto min = 60s;
}
{
    using std::operator""s; // makes both std::literals::string_literals::operator""s
                            // and std::literals::chrono_literals::operator""s visible
    auto str = "abc"s;
    auto min = 60s;
}

Note : la règle concernant les spécialisations permet le versionnage des bibliothèques : différentes implémentations d'un modèle de bibliothèque peuvent être définies dans différents espaces de noms inline, tout en permettant à l'utilisateur d'étendre l'espace de noms parent avec une spécialisation explicite du modèle principal :

namespace Lib
{
    inline namespace Lib_1
    {
        template<typename T> class A; 
    }
    template<typename T> void g(T) { /* ... */ }
}
/* ... */
struct MyClass { /* ... */ };
namespace Lib
{
    template<> class A<MyClass> { /* ... */ };
}
int main()
{
    Lib::A<MyClass> a;
    g(a);  // ok, Lib is an associated namespace of A
}
(depuis C++11)

Espaces de noms non nommés

La unnamed-namespace-definition est une définition d'espace de noms de la forme

inline (facultatif) namespace attr  (facultatif) { namespace-body }
inline - (since C++11) si présent, fait de ceci un espace de noms inline
attr - (since C++17) séquence facultative d'un nombre quelconque d' attributs

Cette définition est traitée comme une définition d'un espace de noms avec un nom unique et une using-directive dans la portée courante qui nomme cet espace de noms sans nom (Note : la directive using implicitement ajoutée rend l'espace de noms disponible pour la recherche qualifiée et la recherche non qualifiée , mais pas pour la recherche dépendante des arguments ). Le nom unique est unique sur l'ensemble du programme, mais au sein d'une unité de traduction, chaque définition d'espace de noms sans nom correspond au même nom unique : plusieurs définitions d'espaces de noms sans nom dans la même portée désignent le même espace de noms sans nom.

namespace
{
    int i; // définit ::(unique)::i
}
void f()
{
    i++;   // incrémente ::(unique)::i
}
namespace A
{
    namespace
    {
        int i;        // A::(unique)::i
        int j;        // A::(unique)::j
    }
    void g() { i++; } // A::(unique)::i++
}
using namespace A; // introduit tous les noms de A dans l'espace de noms global
void h()
{
    i++;    // erreur : ::(unique)::i et ::A::(unique)::i sont tous deux dans la portée
    A::i++; // ok, incrémente ::A::(unique)::i
    j++;    // ok, incrémente ::A::(unique)::j
}

Bien que les noms dans un espace de noms sans nom puissent être déclarés avec une liaison externe, ils ne sont jamais accessibles depuis d'autres unités de traduction car leur nom d'espace de noms est unique.

(until C++11)

Les espaces de noms sans nom ainsi que tous les espaces de noms déclarés directement ou indirectement dans un espace de noms sans nom ont une liaison interne , ce qui signifie que tout nom déclaré dans un espace de noms sans nom possède une liaison interne.

(since C++11)

Déclarations using

Introduit un nom qui est défini ailleurs dans la région déclarative où cette déclaration using apparaît.

using typename (optionnel) spécificateur-de-nom-imbriqué identifiant-non-qualifié ; (jusqu'en C++17)
using liste-de-déclarateurs ; (depuis C++17)
typename - le mot-clé typename peut être utilisé si nécessaire pour résoudre les noms dépendants , lorsque la déclaration using introduit un type membre d'une classe de base dans un modèle de classe
nested-name-specifier - une séquence de noms et d'opérateurs de résolution de portée :: , se terminant par un opérateur de résolution de portée. Un simple :: fait référence à l'espace de noms global.
unqualified-id - une expression d'identifiant
declarator-list - liste séparée par des virgules d'un ou plusieurs déclarateurs de la forme typename (optionnel) nested-name-specifier unqualified-id . Un déclarateur peut être suivi d'une ellipse pour indiquer une expansion de paquet , bien que cette forme ne soit significative que dans les définitions de classes dérivées

Les using-declarations peuvent être utilisées pour introduire des membres de namespace dans d'autres namespaces et portées de bloc, ou pour introduire des membres de classe de base dans les définitions de classes dérivées , ou pour introduire des enumerators dans les namespaces, portées de bloc et classes (since C++20) .

Une déclaration using avec plusieurs using-déclarateurs est équivalente à une séquence correspondante de déclarations using avec un seul using-déclarateur.

(depuis C++17)

Pour l'utilisation dans les définitions de classes dérivées, voir using declaration .

Les noms introduits dans la portée d'un espace de noms par une using-declaration peuvent être utilisés comme n'importe quels autres noms, y compris la recherche qualifiée depuis d'autres portées :

void f();
namespace A
{
    void g();
}
namespace X
{
    using ::f;        // la fonction globale f est maintenant visible comme ::X::f
    using A::g;       // A::g est maintenant visible comme ::X::g
    using A::g, A::g; // (C++17) OK : double déclaration autorisée au niveau de la portée du namespace
}
void h()
{
    X::f(); // appelle ::f
    X::g(); // appelle A::g
}

Si, après qu'une déclaration using a été utilisée pour prendre un membre d'un espace de noms, l'espace de noms est étendu et que des déclarations supplémentaires pour le même nom sont introduites, ces déclarations supplémentaires ne deviennent pas visibles via la déclaration using (contrairement à la directive using). Une exception survient lorsqu'une déclaration using nomme un modèle de classe : les spécialisations partielles introduites ultérieurement sont effectivement visibles, car leur lookup s'effectue via le modèle primaire.

namespace A
{
    void f(int);
}
using A::f; // ::f est maintenant un synonyme de A::f(int)
namespace A       // extension de l'espace de noms
{
    void f(char); // ne modifie pas la signification de ::f
}
void foo()
{
    f('a'); // appelle f(int), même si f(char) existe.
}
void bar()
{
    using A::f; // ce f est un synonyme à la fois pour A::f(int) et A::f(char)
    f('a');     // appelle f(char)
}

Les using-declarations ne peuvent pas nommer template-id , ou un namespace , ou un énumérateur scopé (jusqu'à C++20) . Chaque déclarateur dans une using-declaration introduit un et un seul nom, par exemple une using-declaration pour une énumération n'introduit aucun de ses énumérateurs.

Toutes les restrictions sur les déclarations régulières des mêmes noms, le masquage et les règles de surcharge s'appliquent aux using-declarations :

namespace A
{
    int x;
}
namespace B
{
    int i;
    struct g {};
    struct x {};
    void f(int);
    void f(double);
    void g(char); // OK : le nom de fonction g masque la structure g
}
void func()
{
    int i;
    using B::i;   // erreur : i déclaré deux fois
    void f(char);
    using B::f;   // OK : f(char), f(int), f(double) sont surchargées
    f(3.5);       // appelle B::f(double)
    using B::g;
    g('a');       // appelle B::g(char)
    struct g g1;  // déclare g1 de type struct B::g
    using B::x;
    using A::x;   // OK : masque la structure B::x
    x = 99;       // assigne à A::x
    struct x x1;  // déclare x1 de type struct B::x
}

Si une fonction a été introduite par une déclaration using, déclarer une fonction avec le même nom et la même liste de paramètres est incorrect (sauf si la déclaration concerne la même fonction). Si un modèle de fonction a été introduit par une déclaration using, déclarer un modèle de fonction avec le même nom, la même liste de types de paramètres, le même type de retour et la même liste de paramètres de modèle est incorrect. Deux déclarations using peuvent introduire des fonctions avec le même nom et la même liste de paramètres, mais si un appel à cette fonction est tenté, le programme est incorrect.

namespace B
{
    void f(int);
    void f(double);
}
namespace C
{
    void f(int);
    void f(double);
    void f(char);
}
void h()
{
    using B::f;  // introduit B::f(int), B::f(double)
    using C::f;  // introduit C::f(int), C::f(double), et C::f(char)
    f('h');      // appelle C::f(char)
    f(1);        // erreur : B::f(int) ou C::f(int) ?
    void f(int); // erreur : f(int) entre en conflit avec C::f(int) et B::f(int)
}

Si une entité est déclarée, mais non définie dans un espace de noms interne, puis déclarée via une using-declaration dans l'espace de noms externe, et qu'une définition apparaît ensuite dans l'espace de noms externe avec le même nom non qualifié, cette définition est un membre de l'espace de noms externe et entre en conflit avec la using-declaration :

namespace X
{
    namespace M
    {
        void g(); // déclare, mais ne définit pas X::M::g()
    }
    using M::g;
    void g();     // Erreur : tentative de déclarer X::g qui entre en conflit avec X::M::g()
}

Plus généralement, une déclaration qui apparaît dans n'importe quelle portée d'espace de noms et introduit un nom en utilisant un identifiant non qualifié introduit toujours un membre dans l'espace de noms où elle se trouve et non dans aucun autre espace de noms. Les exceptions sont les instanciations explicites et les spécialisations explicites d'un template primaire défini dans un espace de noms inline : parce qu'elles n'introduisent pas de nouveau nom, elles peuvent utiliser un identifiant non qualifié dans un espace de noms englobant.

Directives using

Une using-directive est une block-declaration avec la syntaxe suivante :

attr  (optionnel) using namespace spécificateur-de-nom-imbriqué  (optionnel) nom-d'espace-de-nom ; (1)
attr - (depuis C++11) n'importe quel nombre d' attributs qui s'appliquent à cette directive using
nested-name-specifier - une séquence de noms et d'opérateurs de résolution de portée :: , se terminant par un opérateur de résolution de portée. Un simple :: fait référence à l'espace de noms global. Lors de la recherche des noms dans cette séquence, la recherche ne considère que les déclarations d'espace de noms
namespace-name - un nom d'espace de noms. Lors de la recherche de ce nom, la recherche ne considère que les déclarations d'espace de noms

Les directives using sont autorisées uniquement dans la portée d'un espace de noms scope et dans la portée de bloc. Du point de vue de la recherche de nom non qualifiée de tout nom après une directive using et jusqu'à la fin de la portée dans laquelle elle apparaît, chaque nom du namespace-name est visible comme s'il était déclaré dans l'espace de noms englobant le plus proche qui contient à la fois la directive using et le namespace-name .

La directive using n'ajoute aucun nom à la région déclarative dans laquelle elle apparaît (contrairement à la déclaration using), et n'empêche donc pas la déclaration de noms identiques.

Les directives using sont transitives pour les besoins de la recherche non qualifiée : si une portée contient une directive using qui nomme un namespace-name , qui contient lui-même une directive using pour un certain namespace-name-2 , l'effet est le même que si les directives using du second espace de noms apparaissaient dans le premier. L'ordre dans lequel ces espaces de noms transitifs se produisent n'influence pas la recherche de nom.

namespace A
{
    int i;
}
namespace B
{
    int i;
    int j;
    namespace C
    {
        namespace D
        {
            using namespace A;
            // Les noms de A sont "injectés" dans D.
            // La recherche non qualifiée dans D considère ces noms comme ayant la même
            // portée que la portée globale (par exemple, pour les besoins de masquage de noms).
            // La recherche qualifiée se référant à D (D::nom pour un certain nom)
            // trouvera le même nom que la recherche non qualifiée dans D.
            int j;
            int k;
            int a = i;   // i est B::i, car A::i est masqué par B::i
            int b = ::i; // erreur : il n'y a toujours pas de i dans l'espace de noms global
        }
        using namespace D; // les noms de D et A sont injectés dans C
        int k = 89; // OK de déclarer un nom identique à celui introduit par un using
        int l = k;  // ambigu : C::k ou D::k
        int m = i;  // ok : B::i masque A::i
        int n = j;  // ok : D::j masque B::j
    }
}
// Ce sont toutes des définitions équivalentes :
int t0 = B::i;
int t1 = B::C::a;
int t2 = B::C::D::a;

Si, après qu'une directive using a été utilisée pour nommer un espace de noms, l'espace de noms est étendu et que des membres supplémentaires et/ou des directives using y sont ajoutés, ces membres supplémentaires et les espaces de noms supplémentaires sont visibles via la directive using (contrairement à la déclaration using)

namespace D
{
    int d1;
    void f(char);
}
using namespace D; // introduit D::d1, D::f, D::d2, D::f,
                   // E::e et E::f dans l'espace de noms global !
int d1;            // OK : pas de conflit avec D::d1 lors de la déclaration
namespace E
{
    int e;
    void f(int);
}
namespace D            // extension d'espace de noms
{
    int d2;
    using namespace E; // directive using transitive
    void f(int);
}
void f()
{
    d1++;    // erreur : ambiguïté ::d1 ou D::d1 ?
    ::d1++;  // OK
    D::d1++; // OK
    d2++;    // OK, d2 est D::d2
    e++;     // OK : e est E::e via le using transitif
    f(1);    // erreur : ambiguïté : D::f(int) ou E::f(int) ?
    f('a');  // OK : la seule f(char) est D::f(char)
}

Notes

La directive using using namespace std ; à n'importe quelle portée d'espace de noms introduit chaque nom de l'espace de noms std dans l'espace de noms global (puisque l'espace de noms global est l'espace de noms le plus proche qui contient à la fois std et tout espace de noms déclaré par l'utilisateur), ce qui peut entraîner des collisions de noms indésirables. Cette directive, ainsi que d'autres directives using, sont généralement considérées comme une mauvaise pratique au niveau de la portée de fichier d'un fichier d'en-tête ( SF.7 : N'utilisez pas using namespace au niveau global dans un fichier d'en-tête ).

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_namespace_attributes 201411L (C++17) Attributs pour les espaces de noms

Mots-clés

namespace , using , inline

Exemple

Cet exemple montre comment utiliser un espace de noms pour créer une classe qui a déjà été nommée dans l'espace de noms std .

#include <vector>
namespace vec
{
    template<typename T>
    class vector
    {
        // ...
    };
} // of vec
int main()
{
    std::vector<int> v1; // Standard vector.
    vec::vector<int> v2; // User defined vector.
    // v1 = v2;          // Error: v1 and v2 are different object's type.
    {
        using namespace std;
        vector<int> v3;  // Same as std::vector
        v1 = v3; // OK
    }
    {
        using vec::vector;
        vector<int> v4;  // Same as vec::vector
        v2 = v4; // OK
    }
}

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
CWG 101 C++98 le programme est mal formé si une déclaration de fonction dans la portée
d'un espace de noms ou d'un bloc et une fonction introduite par une
using-declaration déclarent la même fonction (aucune ambiguïté)
autorisé
CWG 373 C++98 la recherche ne considérait les déclarations d'espace de noms que pour
le dernier nom dans l'opérande d'une using-directive (ce qui est
sous-optimal, car les classes ne peuvent pas contenir d'espaces de noms)
la restriction de recherche
s'applique à tous les noms dans les
opérandes des using-directives
CWG 460 C++98 une using-declaration pouvait nommer un espace de noms interdit
CWG 565 C++98 une using-declaration ne peut pas introduire une fonction
identique à une autre fonction dans la même portée, mais
la restriction n'était pas appliquée aux modèles de fonction
appliquer la même restriction
aux modèles de fonction également
CWG 986 C++98 la using-directive était transitive pour la recherche qualifiée seulement transitive pour la recherche non qualifiée
CWG 987 C++98 les entités déclarées dans un espace de noms imbriqué étaient
également membres de l'espace de noms englobant
portées imbriquées exclues
CWG 1021 C++98 il n'était pas clair si une entité dont la définition
est introduite dans un espace de noms via une using-declaration
est considérée comme définie dans cet espace de noms
non définie dans cet espace de noms
CWG 1838 C++98 une définition non qualifiée dans un espace de noms externe
pouvait définir une entité déclarée, mais non définie dans
un autre espace de noms et importée par une using
la définition non qualifiée
se réfère toujours à
son espace de noms
CWG 2155 C++98 la résolution de CWG issue 1838 n'était pas
appliquée aux déclarations de classes et d'énumérations
appliquée

Voir aussi

namespace alias crée un alias d'un espace de noms existant