C++ Boost

Tuple 庫 : 設計邏輯

關於命名空間

曾經有一個關於tuple的命名空間的討論,tuple應該在一個獨立的命名空間還是應該直接在boost命名空間。 根據一般的原則,一個領域的庫(如,graph, python)應該在一個獨立的命名空間,而廣泛使用的部件庫應該在boost命名空間。 Tuple處於一種中間的情況,一方面它能被廣泛使用,另一方面它除了tuple模板外還引入了十分大量的名字。 Tuple最初是在一個子命名空間。經過討論,結果是tuple的定義直接在boost命名空間。經過又一番的討論,tuple又放回一個子命名空間中。 最終的方案(我希望如此)是所有的定義都在命名空間::boost::tuples  ,和最常用的名稱也直接在 ::boost 命名空間。 這通過using聲明來實現 (由 Dave Abrahams 建議):

namespace boost {
namespace tuples {
...
// 庫的所有代碼
...
}
using tuples::tuple;
using tuples::make_tuple;
using tuples::tie;
using tuples::get;
}
在這樣的安排下,構造tuple的構造函數的調用,make_tuple 或者 tie 函數就可以直接使用而不需要命名空間的前綴。 不僅如此,所有操作tuple的函數可通過Koenig-lookup方法找到。 唯一的例外是get<N> 函數,它總是需要提供顯式的模板參數,所以就沒有提供 Koenig-lookup方法。 因此,get函數被提升到 ::boost 命名空間。 所以,對於一個應用程序開發者,tuple的使用接口實際上在命名空間 ::boost  。

其他的名字,組成了一個庫的開發者用的底層的接口(例如cons lists, metafunctions manipulating cons lists, ...),保留在子命名空間::boost::tuples。 注意,雖然下面名字是應用開發者使用的接口 ignore, set_open, set_closeset_delimiter ,但是仍然不直接在boost名命名空間。 原因是這些普通名字很容易發生名字衝突。 還有,這些特性一般不被頻繁使用。

給十分感興趣命名空間設計的人

有一番關於子命名空間::boost::tuples的討論。不使用最自然的名稱"tuple"的理由是,避免和tuple模板有相同的名字。 但是,在boost庫中命名空間的名字很少被設計成複數的形式。 首先,對命名空間和一個類用相同的名字,未曾有人反映有實質的麻煩。這樣我們會考慮把“tuples”改為“ tuple”。但是我們畢竟發現了一些麻煩。編譯器 gcc 和 edg 都把這種命名空間和類名字相同的情況看作編譯錯誤。

namespace boost {
namespace tuple {
... tie(...);
class tuple;
  ...
}
using tuple::tie; // 可以
using tuple::tuple; // 錯誤
...
}
注意,如果用相應的從全局命名空間開始的表示法似乎能夠編譯通過:
using boost::tuple::tuple; // 可以

部件鏈表(cons list)的結束符號 (nil, null_type, ...)

Tuple在內部表示為部件鏈表( cons list )::

tuple<int, int>
繼承:
cons<int, cons<int, null_type> >
null_type 是鏈表的結束符號。 原來是主張使用符號 nil 但是這個符號已經在 MacOS 中使用,這樣可能導致一些問題,所以用 null_type 代替之。 其他被考慮過的名字有 null_tunit (SML語言中的空tuple名)。

注意 null_type 是空tuple的內部表示: tuple<> 繼承 null_type  。

元素索引

使用0基址還是1基址的索引的選擇問題,經過了透徹而深入的討論。得出下面的觀點:

Tuple 的訪問語法 get<N>(a) 或者 a.get<N>() (其中a 是一個 tuple , N 是索引),被認為是第一個觀點的範疇,因此,tuple中第一個元素的索引是0   。

有個建議希望tuple通過使用索引常量如 _1st, _2nd, _3rd   ,來同時提供 1-基址的 如名字般直觀 的索引  。可以通過合適地選擇索引常量,使下面的語法是等價的:

a.get<0>() == a.get(_1st) == a[_1st] == a(_1st);
Tuple庫決定不提供多於一種索引方法,因為下面理由:

Tuple的比較運算

比較操作符的實現是按照字典順序方法。 其他的排序方法也被考慮到,例如方法 (a < b iff for each i a(i) < b(i))。 我們相信,字典順序雖然不是數學上最自然一種,但是是日常編程中頻繁使用到的。

串行化

在tuple串行化中的特殊字符存儲在由ios_base::xalloc分配的空間中,它為long類型對像分配空間。 static_cast 用於long類型和特殊字符類型之間的轉換。 流中如有不能和long類型相互轉換的字符,則不能通過編譯。 這裡可能需要修訂一些地方。 兩種可能的解決方案是:

返回到用戶指引

© Copyright Jaakko Järvi 2001.