Using-declaration
Introduces a name that is defined elsewhere into the declarative region where this using-declaration appears.
using typename (optional) nested-name-specifier unqualified-id ;
|
(1) | ||||||||
using :: unqualified-id ;
|
(2) | ||||||||
nested-name-specifier | - | a sequence of names and scope resolution operators :: , ending with a scope resolution operator. A single :: refers to the global namespace.
|
unqualified-id | - | an id-expression |
typename | - | the keyword typename may be used as necessary to resolve dependent names, when the using-declaration introduces a type
|
Contents |
[edit] Explanation
Using-declarations can be used to introduce namespace members into other namespaces and block scopes, or to introduce base class members into derived class definitions.
[edit] In namespace and block scope
Using-declaration introduces a member of another namespace into current namespace or block scope
#include <iostream> using std::string; int main() { std::string str = "Example"; using std::cout; cout << str; }
See namespace for details.
[edit] In class definition
#include <iostream> struct B { virtual void f(int) { std::cout << "B::f\n"; } void g(char) { std::cout << "B::g\n"; } void h(int) { std::cout << "B::h\n"; } protected: int m; // B::m is protected typedef int value_type; }; struct D : B { using B::m; // D::m is public using B::value_type; // D::value_type is public using B::f; void f(int) { std::cout << "D::f\n"; } // D::f(int) overrides B::f(int) using B::g; void g(int) { std::cout << "D::g\n"; } // both g(int) and g(char) are visible // as members of D using B::h; void h(int) { std::cout << "D::h\n"; } // D::h(int) hides B::h(int) }; int main() { D d; B& b = d; // b.m = 2; // error, B::m is protected d.m = 1; // protected B::m is accessible as public D::m b.f(1); // calls derived f() d.f(1); // calls derived f() d.g(1); // calls derived g(int) d.g('a'); // calls base g(char) b.h(1); // calls base h() d.h(1); // calls derived h() }
Output:
D::f D::f D::g B::g B::h D::h
struct B1 { B1(int); }; struct D1 : B1 { using B1::B1; // The set of inherited constructors is // 1. B1(const B1&) // 2. B1(B1&&) // 3. B1(int) // D1 has the following constructors: // 1. D1() // 2. D1(const D1&) // 3. D1(D1&&) // 4. D1(int) <- inherited }; struct B2 { B2(int = 13, int = 42); }; struct D2 : B2 { using B2::B2; // The set of inherited constructors is // 1. B2(const B2&) // 2. B2(B2&&) // 3. B2(int = 13, int = 42) // 4. B2(int = 13) // 5. B2() // D2 has the following constructors: // 1. D2() // 2. D2(const D2&) // 3. D2(D2&&) // 4. D2(int, int) <- inherited // 5. D2(int) <- inherited };
[edit] Notes
Only the name explicitly mentioned in the using-declaration is transferred into the declarative scope: in particular, enumerators are not transferred when the enumeration type name is using-declared.
A using-declaration cannot refer to a template-id, to a namespace, to a scoped enumerator, to a destructor of a base class or to a specialization of a member template for a user-defined conversion function.
If a using-declaration brings the base class assignment operator into derived class, whose signature happens to match the derived class's copy-assignment or move-assignment operator, that operator is hidden by the implicitly-declared copy/move assignment operator of the derived class.
If two using-declarations inherit the constructor with the same signature (from two direct base classes), the program is ill-formed.