最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

在寫一種很新的代碼

2023-08-14 01:18 作者:genericity  | 我要投稿

大概十多年前的游戲之作,與君和之。


abused c++ : overloading operator<-


(今天不是4月1日,下面的程序也和Stroustrup博士關(guān)于運算符重載那篇著名論文里的

程序不同,應(yīng)該可以在任何合理的C++編譯器上編譯。)


C++的=和==運算符屬于“不數(shù)學(xué)”(unmathematical)的語言特性,當(dāng)設(shè)計新的類型時,

你可能希望比基本類型顯得更“數(shù)學(xué)”一點,也就是說:

用 a<-b 做賦值,用 a=b 表示相等。


我們先定義一個簡單的類型做討論的對象:

struct Int {

Int(int n=0) : value(n) {}


operator int() { return value; }

private:

int value;

};


相等判斷很容易:

struct Int {

// ...

bool operator=(Int rhs) { return value == rhs.value; }

// ...

};


賦值就麻煩一點了,C++并沒有<-這個運算符。

好在a<-b還是個合法的表達(dá)式,解析為a<(-b),也就是operator<(a, operator-(b))。

顯然我們應(yīng)該在operator-的結(jié)果中保存b的值,在operator<中完成賦值操作。


先定義operator-的結(jié)果類型:

template<typename T> struct assignment_tag {

const T& src;


explicit assignment_tag(const T& n) : src(n) {}

};


然后做運算符重載:

struct Int {

// ...

assignment_tag<Int> operator-() { return assignment_tag<Int>(*this); }

void operator<(const assignment_tag<Int>& rhs) { value = rhs.src.value; }

// ...

};


測試一下:

int main()

{

Int a(1), b(2);

cout<<"a="<<a<<" b="<<b<<'\n';

a<-b;

cout<<"a="<<a<<" b="<<b<<'\n';

if (a=b)

cout<<"a=b\n";

else

cout<<"a<>b\n";

}


$g++ overload.cpp -o overload

$overload

a=1 b=2

a=2 b=2

a=b


Bingo! 一共用了9行(算上空行)達(dá)到目的。如果你覺得這個辦法不錯的話,請注意

本文的標(biāo)題。構(gòu)造這個例子的目的,是要演示對C++運算符重載機(jī)制的濫用。


我們看看,在上面的程序中,b<-0會有什么效果:

首先operator-(int)不能被重載,-0一定得到0。于是b<-0相當(dāng)于b<0,而我們沒有定

義operator<(Int, int),于是根據(jù)函數(shù)重載規(guī)則,使用operator<(

b.operator int(), 0),作了一次無意義的比較。


如果可以重載operator-(int)就好了?完全以某一類型為參數(shù)的運算符,從概念上屬

于該類型的interface。既然不能更改基本類型的定義,C++要求重載運算符的參數(shù)不

能全是基本類型是合理的。


問題在于,我定義的兩個運算符的行為與基本類型相差太遠(yuǎn)。沒人期望if (a < (-b))

不是對a和-b比較大?。m然我有意令operator<返回void以禁止此寫法)。這使得我

們的設(shè)計更加的“非數(shù)學(xué)”。


C++可以說是“成人”的語言,正如Stroustrup喜歡說的,"trust the programmer"。當(dāng)

我明確表示我要做一些“危險”的事情時,編譯器認(rèn)為我知道自己在干什么并且準(zhǔn)備為

其后果負(fù)責(zé)??傉J(rèn)為編譯器比你自己更懂得不做什么對你“有好處”的語言,總給人一種

不舒服的感覺。


任何東西都可以被濫用,也可以被利用。C++中可做的事情很多,所以可以濫用的地方

也不少。那么上面這種濫用對應(yīng)的利用是什么?Expression templates。由高優(yōu)先級運

算符(operator-)返回與子表達(dá)式同構(gòu)的信息(assignment_tag),低優(yōu)先級運算符

(operator<)利用此信息完成整個表達(dá)式的運算,這就是expression templates基本實現(xiàn)

方法。


例如:

T a, b, c;

// ...

c = a+b;


你可以分別定義T operator+(T, T)和T::operator=(T),也可以用expression template

的方式做:

struct addition_tag {

const T& lhs

const T& rhs;

addition_tag(const T& lhs_, const T& rhs_)

: lhs(lhs_), rhs(rhs_) {}

};


addition_tag operator+(const T& lhs, const T& rhs)

{ return addition_tag(lhs, rhs); }


T& T::operator=(const addition_tag& src)

{

// do something with *this, src.lhs and src.rhs

}


為什么要這么麻煩?因為知道的信息越多,越有利于優(yōu)化。普通的+和=只知道兩個對

象,而expression templates版本的=知道表達(dá)式中的全部三個對象。expression

templates的初衷就是利用這多出來的信息消去表示中間結(jié)果的臨時對象。


關(guān)于expression templates的詳細(xì)介紹,見T. Veldhuizen, "Expression Templates"

http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html


Q&A


Q: 表示“相等”的operator=不該是普通函數(shù)嗎(像operator==通常的做法)?

A: 應(yīng)該。但是C++要求operator=是非const成員函數(shù)。這也是不應(yīng)該把=這樣常用的

運算符挪作他用的一個原因:它們有很多限制。


Q: assignment_tag似乎沒什么用。令operator-返回T,并重載operator<(T, T)不行

嗎?

A: 可以,但是我要附會到expression templates上去。;-)


Q: 重載b->a等價于a<-b怎么樣?

A: 不行。->的右邊必須是某struct的成員名字,除非使用宏,目前不可能在編譯時

生成一個包含成員"some_random_name"的struct。

如果不嫌長,可以重載-->。同時重載assignment_tag::operator--(int)的話,

甚至可以寫 a<-------b或者b------>a,限制是箭頭向右時'-'必須是偶數(shù)個。


另外,數(shù)學(xué)家似乎只使用a<-b的形式。


Q: 為什么不能寫a<-b<-c,像基本類型的operator=那樣?

A: 我們的目標(biāo)就是和基本類型不一樣。:-)

寫成(a, b)<-c可能更自然:

pair<Int&, Int&> operator,(Int& lhs, Int& rhs)

{ return pair<Int&, Int&>(lhs, rhs); }


void operator<(pair<Int&, Int&> lhs, assignment_tag rhs)

{

lhs.first<rhs;

lhs.second<rhs;

}


類似的手法,(a, b) = (b, a) 或者 a<b<c 都可以做到。但是,再欣賞python

也不該這樣濫用C++。:-(


在寫一種很新的代碼的評論 (共 條)

分享到微博請遵守國家法律
获嘉县| 习水县| 南皮县| 岗巴县| 绥德县| 卓尼县| 西安市| 渑池县| 承德县| 石屏县| 西平县| 和林格尔县| 莆田市| 尉犁县| 东方市| 南通市| 花莲市| 华蓥市| 虹口区| 奇台县| 华容县| 台东市| 高碑店市| 饶平县| 平山县| 洛阳市| 临夏市| 十堰市| 财经| 穆棱市| 广水市| 旬阳县| 新余市| 施秉县| 游戏| 绥芬河市| 潮安县| 海阳市| 临武县| 双峰县| 金川县|