上个月,在CppCon2022上Herb Sutter介绍了他的一个处于实验中的新编译器:CppFront。
他通过该编译器来实践一种潜在的C++替换语法,简称为Cpp2,C++当前语法则称为Cpp1。Herb从2015年就着手设计该项目,如今推了出来,一时激起不小浪花,项目地址为https://github.com/hsutter/cppfront。官方描述如下:Cppfront is a experimental compiler from a potential C++ 'syntax 2' (Cpp2) to today's 'syntax 1' (Cpp1), to learn some things, prove out some concepts, and share some ideas. This compiler is a work in progress and currently hilariously incomplete… basic functions work, classes will be next, then metaclasses and lightweight exceptions.C++这是在自我破局,开辟第二曲线啊!标准是想再次实现C++11那种巨大的成功,使C++再次焕然一新,更加现代、简单、高效。(虽然Herb说这个项目只代表个人的实践,但是好的点子标准也不会放过,而且是实践可行的点子)其实近几年C++的发展速度真不慢,许多特性迟久未入,只是不想刚引入就遭淘汰。当你再次见到C++更新时,很可能又会是像见到了一个新语言一样,语法完全变化,近几次的标准已有这个趋势。下面我将提供一些Cpp2的例子,这些例子都是可以使用CppFront手动编译运行的,大家可以看看它的语法。Cpp2的目标可以概括为两个词:安全和简洁,语法也以此为导向。先来看一个最简单的例子:
main: () -> int = { s: std::string = "world"; std::cout << "Hello " << s << " "; }这就是使用纯Cpp2编写的代码,所有的声明都由原来的r-to-l变为了l-to-r。其实从trailing-return-type开始,C++已经慢慢变成了这种l-to-r形式的语言。可以混合使用Cpp1和Cpp2的语法,但是对于纯Cpp2语法,它可以隐式地引入C++ 23的"import std"模块,因此无需手动添加任何头文件。接着来看一个文件读写的例子:
main: () -> int = { s: std::string = "Lily"; myfile := fopen("dog", "w"); myfile.fprintf("Hello %s! ", s.c_str()); myfile.fclose(); }这个代码的确简单不少,而且fprintf(), fclose()是作为成员函数存在的,这意味着可以触发IDE的智能提示,提升开发效率。下面是一个类型安全的例子:
main: () -> int = { v: std::variant<int, double> = 42.0; a: std::any = "xyzzy" as std::string; o: std::optional<int> = (); test_generic(3.14); test_generic(v); test_generic(a); test_generic(o); std::cout << " "; v = 1; a = 2; o = 3; test_generic(42); test_generic(v); test_generic(a); test_generic(o); } test_generic: ( x: _ ) = { std::cout << std::setw(30) << typeid(x).name() << " value is " << inspect x -> std::string { is int = std::to_string(x as int); is std::string = x as std::string; is _ = "not an int or a string"; } << " "; }Cpp2中函数不需要前置声明,它具有顺序无关性(其实是生成代码的时候自动提供前置声明了)。其中的"_"是隐式模板的通配符,相当于T,而inspect is as等等这些都是Pattern Matching的语法。在CppFront中,typeid().name()返回的类型名称是可读的,因此最终输出如下图。对于指针,许多运算符都被禁止了,看如下例子:
main: () -> int = { words: std::vector<std::string> = ( "decorated", "hello", "world" ); first: *std::string = words.front()&; last: *std::string = words.back()&; while first <= last { print_and_decorate(first*); first++; // unsafe // first + 1; // first[1]; // first~; // delete first; } } print_and_decorate: (thing:_) = std::cout << ">> " << thing << " ";当试图对指针使用这些操作时,将产生编译期错误。上述代码将报错:
error: ++ - pointer arithmetic is illegal - use std::span or gsl::span instead它会推荐你使用更好的替代特性,有些特性甚至内置为了原生特性,比如智能指针,它会推荐你使用unique.new
main: () -> int = { cpp2::Bounds.set_handler(call_my_framework); words: std::vector<std::string> = ( "decorated", "hello", "world" ); s: std::span = words; print_and_decorate( s[3] ); } print_and_decorate: (thing:_) = std::cout << ">> " << thing << " "; call_my_frameword: (msg: * const char) = std::cout << "sending error to my framework... [" << msg << "] ";代码中访问s[3]越界,编译时指定-s标志,便可以帮你开启边界检查,运行之时进行报错。此外,还可以通过第2行的代码设置一个handler,来捕获错误。只有一个表达式的函数,"{}"将作为可选项,省略掉要更加简洁。 此外,Cpp2也支持初始化安全,对此,指针不可赋值为nullptr/0/NULL。看一个例子:
main: () -> int = { cpp2::Bounds.set_handler(call_my_framework); p: *std::string; if std::rand() % 2 { p = words.front()&; } // else { // p = words.back()&; // } print_and_decorate( p* ); } print_and_decorate: (thing:_) = std::cout << ">> " << thing << " ";例子中,p是一个指针,但是赋值语句没有遍及各个分支,访问之时肯定会存在错误。因此它会直接产生编译期错误:
example.cpp2(4,5): error: local variable p must be initialized on both branches or neither branch example.cpp2(6,5): error: "if" initializes p on: branch starting at line 6 but not on: implicit else branch ==> program violates initialization safety guarantee - see previous errors这个特性可以保证变量在使用前初始化。最后,还有一个有意思的特性用于函数多返回值,一个简单的例子:
f: () -> (i: int, s: std::string) = { i = 10; s = "haha"; return; } auto main() -> int { auto [a, b] = f(); std::cout << a << " " << b << " "; }这个代码混合了Cpp1和Cpp2。函数f()具有多个返回值,可以不用借用std::paire与std::tuple等等组件。实际上,它会自动生成一个结构体,作为函数的返回值。该例子生成的为:
struct f__ret { int i; std::string s; };这些例子都来自Herb的演讲内容,他说Cpp2会比原来的C++语法简单和安全10倍,想看的地址为:https://www.youtube.com/watch?v=ELeZAKCN4tY。Cpp2一直只是Herb个人的一个实验性产品,项目必然存在很多缺陷,但正是这些不断的探索,为C++提供了更多可能。 大家觉得目前的Cpp2设计怎样呢?有没有哪些不错的点子?
审核编辑 :李倩
全部0条评论
快来发表一下你的评论吧 !