ADA亚型等效于C
Ada subtype equivalent in C++
C 是否提供与ADA subtype
相似的东西来缩小类型?
例如:
type Weekday is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
subtype Working_Day is Weekday range Monday .. Friday;
no,不是本地。
您所描述的可能是最好的表示为范围的枚举,并伴随着单独的范围枚举,并带有一组枚举的子集,这些枚举与"父母"范围示波器共享数值表示。
您可以进一步定义两者之间的一些转换,但是如果没有反思,就不可能使其全部优雅和直观,至少不是没有硬编码和重复的东西,而不是打败了目的。
在编程C 时,最好尝试完全放弃通过其他语言编程所填写的思维方式。
话虽如此,这实际上是一个很好的功能主意,尽管我不会屏住呼吸!
解决方法:只需使用枚举,然后应用范围检查您需要的位置。
C 枚举和ADA枚举之间还有一些其他差异。以下ADA代码演示了其中一些差异。
with Ada.Text_IO; use Ada.Text_IO;
procedure Subtype_Example is
type Days is (Monday, Tueday, Wednesday, Thursday, Friday, Saturday, Sunday);
subtype Work_Days is Days range Monday..Friday;
begin
Put_Line("Days of the week:");
for D in Days'Range loop
Put_Line(D'Image);
end loop;
New_Line;
Put_Line("Days with classification:");
for D in Days'Range loop
Put(D'Image & " is a member of");
if D in Work_Days then
Put_Line(" Work_Days");
else
Put_Line(" a non-work day");
end if;
end loop;
end Subtype_Example;
该程序的输出是:
Days of the week:
MONDAY
TUEDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
Days with classification:
MONDAY is a member of Work_Days
TUEDAY is a member of Work_Days
WEDNESDAY is a member of Work_Days
THURSDAY is a member of Work_Days
FRIDAY is a member of Work_Days
SATURDAY is a member of a non-work day
SUNDAY is a member of a non-work day
subtype work_days与类型天有IS-A关系。工作_DAYS的每个成员也是日子的成员。在此示例中
ADA中的字符定义为枚举。因此,为特殊用途定义类型字符的子类型很容易。以下示例读取文件中的文本,并计算上大写字母和下案字母的出现数量,忽略了文件中的所有其他字符。
with Ada.Text_IO; use Ada.Text_IO;
procedure Count_Letters is
subtype Upper_Case is Character range 'A'..'Z';
subtype Lower_Case is Character range 'a'..'z';
Uppers : array(Upper_Case) of Natural;
Lowers : array(Lower_Case) of Natural;
File_Name : String(1..1024);
File_Id : File_Type;
Length : Natural;
Line : String(1..100);
begin
-- set the count arrays to zero
Uppers := (Others => 0);
Lowers := (Others => 0);
Put("Enter the name of the file to read: ");
Get_Line(Item => File_Name,
Last => Length);
-- Open the named file
Open(File => File_Id,
Mode => In_File,
Name => File_Name(1..Length));
-- Read the file one line at a time
while not End_Of_File(File_Id) loop
Get_Line(File => File_Id,
Item => Line,
Last => Length);
-- Count the letters in the line
for I in 1..Length loop
if Line(I) in Upper_Case then
Uppers(Line(I)) := Uppers(Line(I)) + 1;
elsif Line(I) in Lower_Case then
Lowers(Line(I)) := Lowers(Line(I)) + 1;
end if;
end loop;
end loop;
Close(File_Id);
-- Print the counts of upper case letters
for Letter in Uppers'Range loop
Put_Line(Letter'Image & " =>" & Natural'Image(Uppers(Letter)));
end loop;
-- print the counts of lower case letters
for Letter in Lowers'Range loop
Put_Line(Letter'Image & " =>" & Natural'Image(Lowers(Letter)));
end loop;
end Count_Letters;
定义了两个字符的亚型。subtype upper_case包含字符值范围从" a"到" z",而subtype lower_case包含字符值范围从" a"到't t os'z'。
创建了两个数组来计算读取的字母。数组鞋面由upper_case值集索引。数组的每个元素都是天然的实例,它是仅包含非负值的整数的预定义亚型。较低的较低_case值索引阵列索引。降低的每个元素也是自然的一个实例。
程序提示文件名,打开该文件,然后一次读取文件一行。每行中的字符被解析。如果字符是上_case字符,则额定字母索引中的数组元素会增加。如果字符是person_case字符,则降低字母索引的数组元素会增加。
以下输出是读取count_letters程序的源文件的结果。
Enter the name of the file to read: count_letters.adb
'A' => 3
'B' => 0
'C' => 12
'D' => 0
'E' => 2
'F' => 13
'G' => 2
'H' => 0
'I' => 21
'J' => 0
'K' => 0
'L' => 36
'M' => 1
'N' => 9
'O' => 7
'P' => 4
'Q' => 0
'R' => 3
'S' => 2
'T' => 3
'U' => 9
'V' => 0
'W' => 0
'X' => 0
'Y' => 0
'Z' => 1
'a' => 51
'b' => 3
'c' => 8
'd' => 19
'e' => 146
'f' => 15
'g' => 16
'h' => 22
'i' => 50
'j' => 0
'k' => 0
'l' => 38
'm' => 13
'n' => 57
'o' => 48
'p' => 35
'q' => 0
'r' => 62
's' => 41
't' => 78
'u' => 19
'v' => 0
'w' => 12
'x' => 2
'y' => 6
'z' => 2
使用C 17引入的std::variant
实现您想要的可能(至少部分(。
struct Monday {};
struct Tuesday {};
/* ... etc. */
using WeekDay= std::variant<Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday>;
以下代码定义了sub_variant_t
,该代码从提交的类型中构造了新的variant
。例如。using Working_Day= sub_variant_t<WeekDay,5>;
从Weekday
获取前五个元素。
template<class T,size_t o,class S>
struct sub_variant_h;
template<class T,size_t o,size_t... I>
struct sub_variant_h<T,o,std::index_sequence<I...> >
{
using type= std::variant<typename std::variant_alternative_t<(I+o),T>... >;
};
template<class T,size_t end, size_t beg=0>
struct sub_variant
{
using type= typename sub_variant_h<T,beg,std::make_index_sequence<end-beg> >:type;
};
template<class T,size_t end, size_t beg=0>
using sub_variant_t = typename sub_variant<T,end,beg>::type;
如果要从较小 type( Working_Day
(复制值较大一个(Weekday
(,则可以使用WeekDay d3= var2var<WeekDay>( d1 );
,其中var2var
定义为如下。
template<class toT, class... Types>
toT
var2var( std::variant<Types...> const & v )
{
return std::visit([](auto&& arg) -> toT {return toT(arg);}, v);
}
请参阅此Livedemo。
可能您可以将分配重载与后条件
Ensures(result > 0 && result < 10);
纯粹的理论。没有尝试过自己。但是你们怎么看?
,但是很有趣地欣赏他们如何将C 上的每次升级为高级功能 ADA程序员认为是理所当然的所有内容。
范围检查的成本。C 的功能具有零成本策略:如果您想要该功能,并且应该为其支付成本,则需要明确。话虽如此,大多数情况下您可以使用一些图书馆或编写自己的图书馆。
另外,当某人试图将Sunday
放入Working_Day
时,您期望什么?例外(很可能(?将其设置为Monday
?将其设置为Friday
?使对象无效?保持相同的价值并忽略(坏主意(?
作为一个例子:
#include <iostream>
#include <string>
using namespace std;
enum class Weekday
{
Sunday= 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
template <class T, T min, T max>
class RangedAccess
{
static_assert(max >= min, "Error min > max");
private:
T t;
public:
RangedAccess(const T& value= min)
{
*this= value;
}
RangedAccess& operator=(const T& newValue)
{
if (newValue > max || newValue < min) {
throw string("Out of range");
}
t= newValue;
}
operator const T& () const
{
return t;
}
const T& get() const
{
return t;
}
};
using Working_Day= RangedAccess<Weekday, Weekday::Monday, Weekday::Friday>;
int main()
{
Working_Day workday;
cout << static_cast<int>(workday.get()) << endl; // Prints 1
try {
workday= Weekday::Tuesday;
cout << static_cast<int>(workday.get()) << endl; // Prints 2
workday= Weekday::Sunday; // Tries to assign Sunday (0), throws
cout << static_cast<int>(workday.get()) << endl; // Never gets executed
} catch (string s) {
cout << "Exception " << s << endl; // Prints "Exception out of range"
}
cout << static_cast<int>(workday.get()) << endl; // Prints 2, as the object remained on Tuesday
}
输出:
1
2
Exception Out of range
2
- 从处理程序捕获时如何获取 Ada 异常消息C++?
- 将ADA API暴露于C/C (可扩展方式)
- ADA亚型等效于C
- 具有不同亚型的参数方法
- 如何从可从C++代码调用的 Ada 源代码构建静态库?
- C++中的多态亚型
- GCC上的亚型参考参数编译错误
- Ada到C++:传递一个无符号的64位值
- 静态绑定期间C++和 Ada 的差异
- 如何将退出代码从 Ada 进程返回到调用的 Windows 进程
- 您可以将 Ada 泛型函数导出到C++
- 在Eclipse中从C++打电话给Ada
- 将带有条件的Ada记录翻译成C++
- 从Ada程序到C++程序的管道连接
- cc1plus:警告:命令行选项 "-Wstrict-prototypes" 对 Ada/C/ObjC 有效,但对 C++ 无效
- 从C++、Java到Ada的类公式化概念
- Ada变体记录是否可以二进制兼容c++联合?
- C++的多态性,亚型
- 与Ada记录/C++结构类型对应的Python是什么