Each name used in a C++ program must be declared before it can be used. A declaration denotes the existence of an name and specifies the kind of language entity the name denotes. Declarations may introduce entities, associate them with names and define their properties. For example, variables, types, functions, templates, or namespaces are entities. The declarations that define all properties required to use an entity are definitions.
If an entity is defined in multiple translation units all definitions must be the same after preprocessing. For non-inline variables with static storage duration and non-inline functions, only a single translation unit can provide a definition. These conditions form the one-definition rule (ODR). Violations of the one-definition rule are not required to be diagnosed by the compiler, they are ill-formed no diagnostic required (IFNDR).
Each declaration that appears in a C++ program is only visible in some possibly discontiguous scopes. Starting from the global scope :: namespaces form potentially nested scopes for declarations. Some declarations form their own scopes nested in other scopes. Within a function’s scope, nested compound-statements introduce nested scopes.
Within a scope, unqualified name lookup can be used to associate a name with its declaration. Within a class template unqualified name lookup will not find names that depend on a template parameter, such as members of a base class template instantiated with the class template parameters.
A qualified name is created by prefixing a name of an entity with the scope-resolution operator and the name of its surrounding scope, as in std::begin, or by accessing members of an object of class type, such as this->member. The prefix for the global scope or a surrounding namespace is often omitted, when not required, e.g., ::std::begin, but might be needed to avoid ambiguities, such as ::read.
Unqualified name lookup leading to an ambiguity is in general ill-formed.
A using declaration makes all declarations of the qualified name accessible in the current scope for unqualified lookup. This includes inheriting constructors in a derived class, that makes constructors of a base class appear to be declared as constructors of the derived class.
A using directive makes all declarations from the given namespace accessible for unqualified lookup in the current scope.
Overload resolution for functions and function templates
A name denoting the called function in a function call expression can refer to multiple function (template) declarations, known as the overload set. Overload resolution is the process used to select the best matching function from the overload set, based on the number and types of the arguments in the function call expression. Overload resolution does not take default arguments into account. After overload resolution C++ mandates there be a single candidate function (template) as the best match, which is called.
If an unqualified name is used in a function call expression and the resulting overload set does not refer to a member function (template), the overload set is extended to include functions declared in namespaces associated with the types of the arguments of the function call expression. In such a context friend functions defined within a class will be considered when an argument of the call is of that class type (hidden friends). This mechanism is called Argument-Dependent Lookup (ADL).
If an expression with an operand of user-declared type uses an overloadable operator, the resulting expression is treated like an unqualified function-call expression calling the corresponding overloaded operator functions, e.g., operator+.
Using hidden friends is a means to limit the size of overload sets for frequently defined function names, such as overloaded operators.
Compiler-provided definitions
In some circumstances C++ implementations are required to implicitly define the destructor, constructors and assigment operators for a class.
Any expression with a relational or equality operator such as a != b a C++ implementation can rewrite the expression to call a user-defined operator== or operator<=>. This mechanism appears to provide the corresponding operator function definitions, but is implemented as a rewrite of the expression.