
作為關於如何創建概念檢查類模板的例子,我們來看看如何為 InputIterator 概念創建一個概念檢查類。完整的定義如下:
template <class X>
struct InputIterator
: Assignable<X>, EqualityComparable<X>
{
private:
typedef std::iterator_traits<X> t;
public:
typedef typename t::value_type value_type;
typedef typename t::difference_type difference_type;
typedef typename t::reference reference;
typedef typename t::pointer pointer;
typedef typename t::iterator_category iterator_category;
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
BOOST_CONCEPT_USAGE(InputIterator)
{
X j(i); // 要求複製構造 same_type(*i++,v); // 要求後綴遞增提領返回 value_type X& x = ++j; // 要求前綴遞增返回 X& } private: X i; value_type v; // 類型推導會失敗,除非參數具有相同類型 template <typename T> void same_type(T const&, T const&); };
首先,作為一種慣例,我們以概念名來命名概念檢查類。接著,由於 InputIterator 是 Assignable 和 EqualityComparable 的精化,所以我們從這兩個概念的檢查類派生新的概念檢查類。本庫會在檢查 InputIterator 概念時自動檢查 Assignable 和 EqualityComparable 的符合性。
再接著,我們將概念的 相關類型
聲明為成員 typedefs. 相關的距離類型要求是有符號整數,且迭代器的類別必須可轉換為 std::input_iterator_tag, 所以我們對這些關係進行斷言。通過概念檢查模板訪問相關類型的語法借鑒了在C++0x中訪問相關類型的 建議
語法。最後,我們用
BOOST_CONCEPT_USAGE 宏來聲明一個函數,對概念的有效表達式進行測試。注意,在這裡你可能需要一點創意:例如,為了檢查
*i++ 是否返回迭代器的值類型,我們將這兩個值傳給 same_type 成員函數模板,後者要求兩個參數具有相同類型,包括引用和cv限定符。這是一個有漏洞的檢查,但總比沒有任何東西好一點。
你可能覺得奇怪,為什麼在上例中將 i 和 v
聲明為數據成員。為什麼我們不像以下這樣寫?
BOOST_CONCEPT_USAGE(InputIterator)
{
X i; // 創建我們需要的值 value_type v; X j(i); // 要求複製構造 same_type(*i++,v); // 要求後綴遞增提領返回 value_type X& x = ++j; // 要求前綴遞增返回 X& }
不幸的是,這段代碼不能很好地工作,因為它無意中強制要求了 X 及其值類型都必須是可缺省構造的。另一方面,因為 InputIterator 模板的實例永遠不會被構造,編譯器無需檢查其數據成員需要如何構造(C++標準第14.7.1 9節)。為此,你應該總是將用法模式所需的值聲明為數據成員。
在概念定義中的這類錯誤可以通過使用 概念原型 檢測出來,但是提前避免它們都是更好些的。
本庫中對於概念精化以及訪問相關類型的語法,都借鑒了在C++0x中相應的 建議 語法。不過,C++0x 會使用 “signatures簽名” 而不是用法模式來描述一個概念中的類型所參與的有效操作,所以將你的概念檢查類轉換為語言支持的概念時,你需要將你的用法函數轉換為一系列簽名。
Next: Concept Covering and
Archetypes 概念的充分性和原型
Prev: Using Concept
Checks 使用概念檢查
| Copyright © 2000 | Jeremy Siek(jsiek@osl.iu.edu) Andrew Lumsdaine(lums@osl.iu.edu), 2007 David Abrahams. |