Using Directives in C++

Last time I talked about namespaces in C++ and I touched a little on the subject of using directives, and using declarations. Since I think it is very important to understand the difference between the two, I’ve decided to talk about them. Before you continue, however, you need to really have understood the concepts that we talked about before, specially those of namespaces, and scope, as well as how name resolution works.

Scope — A Second Look

Lets give scope a second look. We’ve already said that the scope of a variable is everywhere that variable is available, or visible. This time, we will talk about variables, but you should assume that this applies to all kinds of entities that have an identifier, such as functions, constants, and classes.

C++ has block scope. This means that a new scope is defined for every block of code. A block of code is usually delimited by curly braces. Following this logic, we can see that if you create an if statement, everything in the if branch is in its own scope, and if you have an else branch, everything in it is in its own scope as well. If you define a function, that function creates its own scope, and everything inside that function is in the scope of that function.

It is really important to understand this, because scope will usually determine where the best place to define a variable is. For example, if you want a variable to be accessible only from withing a function, then the best place to define that variable is inside the function. Scope will prevent the variable from being accessed from outside the function.

Another example would be if you want to create a variable and work with it only if some condition is met. In this case, the best place to define that variable is inside the if statement. However, if you want to have a variable and change its value depending on a certain condition being met, then you would have to define the variable outside of the if statement, and only change its value if the condition is met. This way you can access the variable from outside the if statement once its value has been changed.

The Scope Chain

We didn’t talk about the scope chain last time, and it is time we talk about it. As blocks get nested, scopes get nested as well, and this forms a scope chain. Think for example of a function that has an if statement inside of it:


int main() {
  if (1 == 1) {
    //do something here.
  }
}

In this code we have two different levels of scope. One is the scope defined by the main function, and the other one is define by the block of the if statement. The scope of the if statement is inside of that of the main function. We can say that the scope of the if statement is bellow the scope of the function in the scope chain.

In most programming languages you can move up the scope chain, but not downwards.This means that the code in the if statement has access to anything defined before the if statement in the main function. However, nothing in the main function can access anything defined inside the if statement unless it is also in the if statement. Lets take a look at some examples:


int main() {
  int number = 1;
  if (1 == 1) {
    int if_number = 2
  }
  cout << number << endl;
}

Note that I’ve omitted some boilerplate code here, like the inclusion of the iostream header, as well as the return statement of the main function.

In this example, cout can access the variable number because it was defined in the same scope, that of the main function. Now take a look at the next example:


int number = 1;
int main() {
  if (1 == 1) {
    int if_number = 2
  }
  cout << number << endl;
}

In this example, number was defined outside of the scope of the main function, but cout can still navigate up the scope chain and have access to the number variable. Now, consider the following:


int number = 1;
int main() {
  if (1 == 1) {
    int if_number = 2
  }
  cout << if_number << endl;
}

Here, there is an problem. cout is now trying to access if_number which was defined in the scope of the if statement. cout cannot navigate down the scope chain, therefore it does not have access to the if_number variable. Now consider this example:


int number = 1;
int main() {
  if (1 == 1) {
    int if_number = 2
  }
  if (2 == 2) {
    cout << if_number << endl;
  }
}

In this example, it looks like if cout had access to the if_number variable, because it is defined up the scope chain. However, that is not the case. When name lookup starts, it goes up the scope chain, to the scope of the main function, however, if we wanted to access the variable, we would have to go down into the scope of the if statement, and that is not possible.

The using Directive

Now that we have a better understanding of scope, lets look at the using directive.

A using directive is a way to specify that we are going to be accessing members contained within a namespace using only their name, rather than their fully qualified names, which would include the namespace as well as the name. Consider this:


namespace myNs {
  int myNumber = 9001; // myNumber is over 9000!
}

The name of the variable in this case is “myNumber”, and its fully qualified name is “myNs::myNumber”.

By using the using directive using namespace myNs we can refer to the variable by its name without specifying the namespace that it belongs to.

How does this work anyway?

A using directive works by placing everything belonging to the referred namespace inside the closest namespace shared by the referred namespace and the current scope. Good luck understanding what that means…

But if you don’t understand it, don’t worry. I will explain it by example in my next post.