5

When trying to get the first or last index of an unbounded string, as shown in this program

with Ada.Strings; use Ada.Strings; -- for `Backward`
with Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;

procedure Foo is
    package U_Str renames Ada.Strings.Unbounded;

    S : U_Str.Unbounded_String := U_Str.To_Unbounded_String ("example unbounded string");
    I : Natural := U_Str.Index (Source => S,
                                Pattern => "s",
                                Going => Backward,
                                From => S'Last);
begin
    Put_Line (I'Image);
end Foo;

GNAT complains about U_Str.Unbounded_String being a private type:

$ gnatmake foo.adb
x86_64-linux-gnu-gcc-10 -c foo.adb
foo.adb:12:41: prefix for "Last" attribute may not be private type
gnatmake: "foo.adb" compilation error

I don't understand this, the same program with a regular String works fine:

with Ada.Strings; use Ada.Strings; -- for `Backward`
with Ada.Strings.Fixed;
with Ada.Text_IO; use Ada.Text_IO;

procedure Foo is
    package F_Str renames Ada.Strings.Fixed;

    S : String := "example fixed string";
    I : Natural := F_Str.Index (Source => S,
                                Pattern => "s",
                                Going => Backward,
                                From => S'Last);
begin
    Put_Line (I'Image);
end Foo;
$ gnatmake foo.adb 
x86_64-linux-gnu-gcc-10 -c foo.adb
x86_64-linux-gnu-gnatbind-10 -x foo.ali
x86_64-linux-gnu-gnatlink-10 foo.ali
$ ./foo 
 15

Do unbounded strings have no 'First and 'Last attributes? The Ada Reference Manual only states

The following attributes are defined for a prefix A that is of an array type (after any implicit dereference), or denotes a constrained array subtype

but it does not say anything about private types. Is this a GNAT bug or did I miss something?

1
  • 2
    A complement to the answer: the reason 'First and 'Last are available for String is that a String is a plain array, with a lower bound and an upper bound. Commented Dec 3, 2024 at 19:59

1 Answer 1

5

The attributes 'First and 'Last are indeed unavailable for private types. Instead, note that "Unbounded_String represents a String whose low bound is 1 and whose length can vary conceptually between 0 and Natural'Last." Moreover, "The function Length returns the length of the String represented by Source." As a result, you can use the Length function to search from the string's end.

From => U_Str.Length(S));

This yields the value 19 for I in your first example.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.