
我們已經討論了選擇最小要求(概念)的重要性,但同樣重要的是,必須驗證所選的概念對算法而言是充分的。即所有可能的用戶錯誤都將被概念檢查所捕獲而不會漏過。概念的覆蓋度可以通過使用 archetype classes原型類 來驗證。原型類是與特定概念相對應的接口的精確實現。原型類的運行期行為並不重要,其中的函數可以為空。然後一個簡單的測試程序可以將原型類作為組件的輸入來編譯。如果程序通過編譯,則可以肯定概念已經充分覆蓋組件。以下代碼示範了 Input Iterator 概念的原形類。必須要小心確保原型是與概念精確匹配的。例如,概念要求 operator*() 的返回值必須可轉換為 value type。它並沒有進一步要求返回值是 T& 或是 const T&. 這意味著以 T& 或 const T& 作為原型類的返回類型都是錯誤的。正確的方法是創建一個可轉換為T的返回類型,如我們在下面所寫的 reference. 原型類測試的有效性完全信賴於它與概念吻合的精確度,必須小心地進行(人工)檢查。
template <class T>
class input_iterator_archetype
{
private:
typedef input_iterator_archetype self;
public:
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
struct reference {
operator const value_type&() const { return static_object<T>::get(); }
};
typedef const T* pointer;
typedef std::ptrdiff_t difference_type;
self& operator=(const self&) { return *this; }
bool operator==(const self&) const { return true; }
bool operator!=(const self&) const { return true; }
reference operator*() const { return reference(); }
self& operator++() { return *this; }
self operator++(int) { return *this; }
};
泛型算法通常會用多個普通類型來實例化,以進行測試。例如,你可以用普通的指針來作為迭代器應用到 std::stable_sort() 上。雖然這適合於測試算法的運行期行為,但無助地確認概念的充分條件,因為C++的類型並不符合某個特定的概念,它們通常提供比某個概念的最小功能要求多 得多的特性。即是說,雖然函數模板對於給定的類型可以通過編譯,但概念所要求的還是達不到函數真正所要求的。這正是為什麼要在用普通類型進行測試以外,還 要使用原型類來編譯的重要性。
以下是來自 stl_concept_covering.cpp
一些摘要,示範了如何用原型來檢查文檔中對 std::stable_sort()
的要求。在這個例子中,看起來在SGI STL文檔中,好像漏掉了 CopyConstructible 和 Assignable
的要求(試一下刪掉這些原型)。Boost的原型類被設計為可以分層的。在這個例子中,迭代器的值類型由三個原型組成。在 archetype 類的參考 中,名為Base的模板參數指出了可以使用分層原型的地方。
{
typedef less_than_comparable_archetype<
sgi_assignable_archetype<> > ValueType;
random_access_iterator_archetype<ValueType> ri;
std::stable_sort(ri, ri);
}
Next: Programming with
Concepts 用概念編程
Prev: Creating Concept Checking
Classes 創建概念檢查類
| Copyright © 2000 | Jeremy Siek(jsiek@osl.iu.edu) Andrew Lumsdaine(lums@osl.iu.edu), 2007 David Abrahams. |