The use of "use". Does it do more than remove the need for prefix?

Viewed 91

The following program (main.adb) will not compile, giving the error:

main.adb:10:15: expected private type "ThreadName" defined at config.ads:5
main.adb:10:15: found private type "Ada.Strings.Unbounded.Unbounded_String"
main.adb:11:45: expected private type "Ada.Strings.Unbounded.Unbounded_String"
main.adb:11:45: found private type "ThreadName" defined at config.ads:5

Yet, when I add a "use Config;" clause and remove the Config. prefix to the declaration of MyName in main.adb, it compiles cleanly and works correctly. I had understood that the use of the "use" clause was simply to allow me to avoid the namespace prefixes, but it appears to do a lot more. Could anyone explain?

The file config.ads contains

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package Config is
    type ThreadName is new Unbounded_String;
end Config;

and my main.adb contains:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Config;

procedure Main is

    MyName : Config.ThreadName;

begin
    MyName := To_Unbounded_String ("Chris");
    Put_Line ( "The name is: " & To_String (MyName));
end Main;
2 Answers

Use also makes the implicitly defined operations on the types defined in your package visible ... that includes To_Unbounded_String and vice versa in this example.

There is also Use Type which makes the operations visible without otherwise polluting the namespace with everything in the package; but it only exposes the operators (+,-,= etc) while

with Config;
use all type Config.Threadname;

will make the type, operators, and other subprograms visible for Config.Threadname without exposing anything else in the package.

The use clause makes the contents of a package visible within the scope of the use clause. In your example above you "with" config but do not "use" config. On the other hand Ada.Strings.Unbounded has a "use" clause, making its types, constants, and subprograms visible within the scope of Main.

procedure Main is

MyName : Config.ThreadName;

begin
   MyName := To_Unbounded_String ("Chris");
   Put_Line ( "The name is: " & To_String (MyName));
end Main;

MyName is declared to be an instance of the type Config.ThreadName. ThreadName is declared to be a separate type from Ubounded_String. Therefore the operations visible in the Ada.Strings.Unbounded package do not apply to instances of ThreadName. If you "use" Config the compiler will have visibility to all the subprograms applicable to type ThreadName, and will be able to determine which "To_Unbounded_String" function to call based upon the parameter type and the function return type.

The side effect of the "use" clause is to reduce the need to write package_name.subprogram, but its primary purpose is to make the public contents of a package visible within the scope of the compilation unit employing the "use" clause.

Related