Reputation:
I'm learning ada and I'm trying to implement an addition overload for an enum.
Basically I want to be able to add an Integer to a Day type and get the resulting Day value. So MONDAY + 2 => WEDNESDAY.
Here is my simplified code:
procedure overload is
type Day is (
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
);
day1 : Day := Monday;
function "+" (left: Day; right: Integer) return Day is
-- how would I handle this here? I want to basically say
-- if Day + Integer > Saturday then
-- wraparound back to Sunday
return DayValue;
begin
for x in 0 .. 7 loop
Ada.text_io.put_line("Monday + " & Integer'Image(x) & " = " & Day'Image(day1 + x));
end loop;
end overload;
Upvotes: 5
Views: 550
Reputation: 3358
I would use PragmARC.Wrapping
:
with PragmARC.Wrapping;
function "+" (Left : Day; Right : Integer) return Day is
package Wrapping is new PragmARC.Wrapping (Item => Day);
use Wrapping;
Result : Day := Left;
begin -- "+"
Change : for I in 1 .. abs Right loop
Result := (if Right < 0 then Wrap_Pred (Result) else Wrap_Succ (Result) );
end loop Change;
return Result;
end "+";
Upvotes: 2
Reputation: 5051
While you have an answer to get the position value associated with a enumeration value, do not think this is the same as an enum in C. Ada enumerations are not numeric types.
You can iterate through a range of enumeration values using a for loop as in
for the_day in Day loop in loop
Put_Line(Day'Image(the_day));
end loop;
If you want to print the current day and the next day you can use the 'Succ attribute.
for the_day in Day loop
Put(Day'Image(the_day) & " the next day is ");
if the_day = Day'Last then
Put_Line(Day'Image(Day'First));
else
Put_Line(Day'Image(the_day'Succ));
end if;
end loop;
Upvotes: 3
Reputation: 3641
You can use the 'Pos and 'Val attributes to do it. 'Pos returns the position of the supplied day relative to the first option (0 indexed) while 'Val takes a Pos value and returns the day type value:
return Day'Val(Day'Pos(Left) + Right);
For wraparound check the 'Pos value of Saturday vs the 'Pos value of left + the right value and use Day'Val(0) for Sunday
Or switch your input type of Right from Integer to Natural and use modulus math:
return Day'Val((Day'Pos(left) + Right) mod 7);
You can even get fancy and make a constant for the 7:
Day_Mod : constant := Day'Pos(Day'Last) - Day'Pos(Day'First) + 1;
and then it becomes
return Day'Val((Day'Pos(left) + Right) mod Day_Mod);
Upvotes: 6