在前一篇文章中有这么一段代码:
change_speed(Speed s); // better: the meaning of s is specified // 较好:定义了s的含义// ...change_speed(2.3); // error: no unit 错误:没有单位change_speed(23m / 10s); // meters per second 米每
第1行是函数声明,第4行是简单的调用调用都没有什么可说的,第5行就不一样了:竟然可以支持带单位运算!
一般来讲,C++或者C语言都支持类似于25L之类的写法,这里的L就是字面量运算符。从C++11开始,C++语言引入的一项技术:通过重载operator ""(双引号)后缀运算符实现的(称为literal operator,字面量运算符)。
假设我们有如下一个Distance类:
struct Distance{ explicit Distance(double val) :meters(val) {} long double meters{ 0 };};我们可以定义如下的字面量运算符用以支持m和km单位:
Distance operator""km(long double val){ return Distance(val * 1000);}Distance operator""m(long double val){ return Distance(val);}Distance operator""km(unsigned long long val){ return Distance(val * 1000);}Distance operator""m(unsigned long long val){ return Distance(val);}经过这样的定义之后,以下的代码都是合法的:
Distance d0{ 1000 };Distance d1{ 1.0km };其中第二种形式定义d1之后,d1.meters的值是1000。我们也可以以同样的方式定义一个Time类,这个类支持sec和hour单位:
struct Time{ explicit Time(double val):seconds(val) {} long double seconds{ 0 };};Time operator""sec(long double val){ return Time(val);}Time operator""hour(long double val){ return Time(val * 3600);}Time operator""sec(unsigned long long val){ return Time(val);}Time operator""hour(unsigned long long val){ return Time(val * 3600);}接下来的定义支持除法运算符的Speed类就是常规操作了:
struct Speed{ explicit Speed(double val) :speed(val) {} long double speed;};Speed operator /(Distance d, Time t){ return Speed(d.meters / t.seconds);}这些准备工作完成之后,就可以像下面这样编程了:
int main(){ Distance d0{ 1000 }; Distance d1{ 1000.0m }; Time t1{ 2.0hour }; Speed s1(d1 / t1); std::cout << "s1=" << s1.speed << "m/s" << std::endl; Speed s2{ 7.8km / 1sec }; std::cout << "s2=" << s2.speed << "m/s" << std::endl; return 0;}是不是很神奇?
注意:c++标准保留所有非下划线开头的字面量后缀形式,一般情况下自定义字面量运算符时建议使用下划线开头。如果考虑通用性,本文中定义的字面量运算符应该是_m,_km,_sec,_hour。
参考资料:
User-defined literals (since C++11):
https://en.cppreference.com/w/cpp/language/user_literal
User-Defined Literals (C++):
https://docs.microsoft.com/en-us/cpp/cpp/user-defined-literals-cpp?redirectedfrom=MSDN&view=vs-2019
觉得本文有帮助,欢迎点赞并分享给您的朋友。
阅读更多更新文章,请关注微信公众号【面向对象思考】