4.2.1 User-Defined Literals
Using one or more of the aspects defined below, a
type may be specified to allow the use of one or more kinds of literals
as values of the type.
Static Semantics
The following type-related
operational aspects (collectively known as
user-defined literal aspects)
may be specified for any type
T:
Integer_Literal
This aspect is specified by a
function_name
that statically denotes a function with a result type of
T and
one
in parameter that is of type String and is not explictly aliased.
Real_Literal
This aspect is specified by a
function_name
that statically denotes a function with a result type of
T and
one
in parameter that is of type String and is not explictly aliased.
String_Literal
This aspect is specified by a
function_name
that statically denotes a function with a result type of
T and
one
in parameter that is of type Wide_Wide_String and is not explictly
aliased.
User-defined literal aspects are inherited according
to the rules given in
13.1.
When a numeric literal is interpreted as a value
of a non-numeric type
T or a
string_literal
is interpreted a value of a type
T that is not a string type (see
4.2), it is equivalent to a call to the subprogram
denoted by the corresponding aspect of
T: the Integer_Literal
aspect for an integer literal, the Real_Literal aspect for a real literal,
and the String_Literal aspect for a
string_literal.
The actual parameter of this notional call is a
string_literal
having the textual representation of the original (numeric or string)
literal.
Such a literal is said to be a
user-defined literal.
Legality Rules
The Integer_Literal or Real_Literal aspect shall
not be specified for a type T if the full view of T is
a numeric type. The String_Literal aspect shall not be specified for
a type T if the full view of T is a string type.
For a nonabstract type, the function directly specified
for a user-defined literal aspect shall not be abstract.
For a tagged type with a partial view, a user-defined
literal aspect shall not be directly specified on the full type.
If a nonabstract tagged type inherits any user-defined
literal aspect, then each inherited aspect shall be directly specified
as a nonabstract function for the type unless the inherited aspect denotes
a nonabstract function and the type is a null extension.
In addition to the places where Legality Rules normally
apply (see
12.3), these rules also apply in
the private part of an instance of a generic unit.
Bounded (Run-Time) Errors
It is a bounded error if the
evaluation of a literal that has an expected type with a specified user-defined
literal aspect propagates an exception. Either Program_Error or the exception
propagated by the evaluation is raised at the point of use of the value
of the literal. If it is recognized prior to run time that evaluation
of such a literal will inevitably (if executed) result in such a bounded
error, then this may be reported as an error prior to run time.
Examples
subtype Roman_Character is Character
with Static_Predicate =>
Roman_Character in 'I' | 'V' | 'X' | 'L' | 'C' | 'D' | 'M';
Max_Roman_Number : constant := 3_999; -- MMMCMXCIX
type Roman_Number is range 1 .. Max_Roman_Number
with String_Literal => To_Roman_Number;
function To_Roman_Number (S : String) return Roman_Number
with Pre => S'Length > 0 and then
(for all Char of S => Char in Roman_Character);
function To_Roman_Number (S : String)
return Roman_Number
is
(
declare
R :
constant array (Integer
range <>)
of Integer :=
(
for D
in S'Range => Roman_Digit'Enum_Rep
(Roman_Digit'Value (''' & S(D) & '''))); --
See 3.5.2 and 13.4
begin
[
for I
in R'Range =>
(
if I < R'Last
and then R(I) < R(I + 1)
then -1
else 1) * R(I))]
'Reduce("+", 0)
);
X : Roman_Number := "III" * "IV" * "XII"; -- 144 (that is, CXLIV)
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe