Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does using mean in c++?

Tags:

c++

using

Like :

using ::size_t; using ::fpos_t; using ::FILE;

In fact it's a question inspired by the comment under this question:

When is .h not needed to include a header file?

like image 1000
user198729 Avatar asked Mar 28 '10 10:03

user198729


2 Answers

This is called using declaration. There are actually two ways you can use the using keyword. There is a third special form of using declarations used inside class definitions, but i'll focus on the general using declaration here. (see below).

  • using declaration
  • using directive

These have two very different effects. A using declaration declares a name to be an alias to another declaration or a set of declarations (if you were to name a set of overloaded functions). The name is declared in the current scope. That is, you can use it inside blocks too

int main() {
  using std::swap;
  // ...
}

This is quite useful if you use a name very often locally and you don't want to prefix it in all uses, and it's also useful in implementing the swap using argment dependent lookup idiom.

A using directive names a namespace and does not declare any names. Instead it will modify name lookup to find names that aren't really declared where it thinks they are. For unqualified name lookup, it find names declared in the enclosing namespace that encloses both the using directive and the target namespace. All names that are declared in the target namespaces will be found:

int cout;
int main() {
  using namespace std;
  // cout << 1; ambiguous!
}

Here, cout will be thought as being declared twice in the global namespace, and causes an ambiguity (:: encloses both main and std). In qualified namelookup, it will build the transitive closure of a namespace with all the namespaces named in using directives.

using namespace foo;

int main() {
  ::c++; 
}

c is not only looked up in the global namespace, but also in the namespace foo and in the namespaces that foo has using directives for and so on. If however the global namespace would contain a direct declaration (including a using declaration), that declaration will hide the declarations found indirectly by using directives:

using namespace foo;
int c;

int main() {
  ::c++; // not ambiguous!
}

Using declarations can appear in many places, including inside class definitions. Its meaning is similar to its meaning otherwhere with an important restriction: It declares a name to be an alias to one or more declarations, but the declarations must be members of a base class. This is very useful for making names visible in a derived class that would otherwise be hidden by the same name declared there

struct base {
  void f();
};

struct derived : base {
  using base::f; // name "f" declared in derived
  void f(int); // overloads the using declaration
};

Now you can call d.f(). If there were no using declaration, then name lookup would only find one declaration of f in derived and stop lookup, not delving into the base class scope:

derived d;
d.f(); // invalid without the using declaration
d.f(0); // valid with or without the using declaration

// explicitly starting lookup in base: valid with or without the using declaration
d.base::f();

It also allows to change the accessibility of base-class members, although you should use that sparingly :)

In practice, i found it useful for making virtual member function re-visible:

struct base {
  virtual void f();
  virtual void f(int);
};

struct derived : base {
  // using base::f; would solve it
  virtual void f() { ... }
};

Oops - now d.f(0); is invalid because name lookup only finds the zero parameter f! The using directive would solve it. Notice that if you alias a function declaration that has the same parameter types and constness as an explicit declaration (like f() in this case), then the explicit declaration will still hide the one that the using declaration is an alias for - so both f() functions won't conflict in this case.

An alternative to solve this is using the non-virtual interface idiom

struct base {
  void f() { do_f(); }
  void f(int) { do_f(0); }

private:
  virtual void do_f();
  virtual void do_f(int);
};

struct derived : base {
private:
  virtual void do_f() { ... }
};

struct derived1 : derived {
private:
  virtual void do_f(int) { ... }
};

Now, both d.f(0) and d.f() are valid no matter on what object you call it.

like image 174
Johannes Schaub - litb Avatar answered Sep 19 '22 00:09

Johannes Schaub - litb


Unfortunately the example you're looking at is obscure.

using ::_Filet;

As others have noted, the using declaration makes a name from the specified namespace available in the current namespace. In that file there appear to be no namespaces opened, so you'd assume the current namespace is the global namespace, and also the :: with nothing before it addresses the global namespace. So here we seem to be moving a name from the global namespace into the global namespace. What's up with that?

The answer is in the use of a macro:

_STD_BEGIN

This is defined as namespace std {. So what the using declarations are doing is making those names appear in the std namespace, where otherwise they would only be in the global namespace.

like image 45
Daniel Earwicker Avatar answered Sep 19 '22 00:09

Daniel Earwicker