Uniform Function Call Syntax
导语
现在手头有一个库,只有头文件和共享库(.so、.dll whatever),需要对头文件中的类增加方法,可是这个类标记了
final
,这时候该怎么办呢?
Rust的做法
现在有一个简单的库叫做Point
, 这个库只有两个方法new
和enlarge
现在需要为其添加新的功能,即:shrink
。可以这么做:
当然, 如果有多个trait
都提供了同样的接口,这时候就需要消歧义了,Rust的做法是这样
trait Foo {
fn moha(&self);
}
trait Bar {
fn moha(&self);
}
struct Elder;
impl Foo for Elder {
fn moha(&self) {
println!("+1s");
}
}
impl Bar for Elder {
fn moha(&self) {
println!("-1s");
}
}
fn main() {
let elder = Elder;
<Elder as Foo>::moha(&elder); // print `+1s`
<Elder as Bar>::moha(&elder); // print `-1s`
}
看到这里, 你可能已经发现, 在Rust里面 elder.moha()
与Foo::moha(&elder)
是等价的。
C++的做法
#include <iostream>
struct Point {
int x;
int y;
static auto New() -> Point {
return Point {0, 0};
}
auto enlarge() -> Point& {
this->x += 2;
this->y += 2;
return *this;
}
};
std::ostream& operator<< (std::ostream& os, const Point& p) {
os << "Point { x: " << p.x << ", y: " << p.y << " }\n";
return os;
}
struct MyPoint : Point {
auto shrink() -> Point& {
this->x -= 2;
this->y -= 2;
return *this;
}
};
int main() {
MyPoint mp;
std::cerr << mp;
mp.enlarge();
std::cerr << mp;
mp.shrink();
std::cerr << mp;
}
现在有两个明显的问题:
- MyPoint != Point
- Point是
final
修饰的怎么办?
那么,可不可以这样
// define a method for Point
auto shrink(Point& p) -> Point& {
p.x -= 2;
p.y -= 2;
return p;
}
// then call it
p.shrink();
这里以Rust扩展方法的做法为例子其实并不很恰当。目的为了与final
修饰的C++类的扩展做对比。 上面shrink
只是一个普通的函数,但通过.shrink
来调用,正是uniform function call
的一部分。
摘自A bit of backgorund for unified call proposal的一段话: > So, we are left with a simple proposal to allow f(x,y) to find x.f(y) where f(x,y) wouldn’t work today. This solves the problem for library writers and their users along the lines of the STL:
- Library designers don’t have to force users to use one preferred syntax or to duplicate the implementation to handle both.
- It allows us to write simple concepts for new libraries.
- We no longer have to write call-syntax adapters.
- We can in many cases add functionality to an abstraction without modifying a class
- We no longer have to bother the users with the distinction between member functions and helper functions.
UFCS与Concepts
待续…
参考
Rust UFCS RFC
C++ UFCS Proposal
background for unified call proposal
UFCS Wiki
N4474