Concepts vs. Type Traits (vs. Reflection)
我在《HasSwap
》一文裡面試著以 HasSwap
type-trait class 改寫 std::swap
,並在最後提到「Type traits 基本上可算是 compile-time reflection 吧」。無獨有偶,C++0x proposal N1775《A Case for Reflection》亦在 "3 How we use reflection - 3.2 Algorithm Tailoring" 提到類似應用:
Among the most common use cases is the desire to take advantage, in generic code, of a specific client class’s features. If a class provides, say, a member
sort()
, a generic algorithm is typically better off to call it rather thanstd::sort()
, for instances of that class. While numerous coding practices have been proposed to handle such a scenario, none has achieved widespread acceptance, and some have even (with some justification) been labeled “arcane.”
正好呼應我的說法。(Reflection in C++ 目前的狀態是 "not ready for C++0x, but encourage work to continue",所以應該不會出現在 C++0x 之中。)然後我又想到:concepts 不也是一種描述型別特徵的方式嗎?以 Stroustrup et al. 所提議的 usage pattern 表述的話(C++0x proposal N1782, N1886, ...):
concept Swappable<typename T> { Var<T> t; // 若單純寫 "T t;",會被詮釋為「T 為 default-constructible」 Var<T> u; t.swap(u); };
(或許還得加上一些「喚起 swap
後,t
和 u
的值互換」之類的語意描述,不過我不知道 concept system 能不能(應不應該)這麼做。)然後再透過 template overloading:
namespace std { template <CopyConstructible && Assignable T> void swap(T& a, T& b) { T temp(a); a = b; b = temp; } template <Swappable T> void swap(T& a, T& b) { a.swap(b); } }
就可完成在 C++03 必須以「一個攜帶型別資訊的額外參數」和「函式重載」實施的 dispatch。看看 TR1 裡面的 type-trait classes,判斷的都是一些比較本質上的型別特性,例如 is_integral
, is_array
, has_trivial_copy
, has_nothrow_assign
,乃至於二元的 is_convertible
, is_base_of
,相較於 concept 描述型別行為("usage pattern" 很清楚指出這個性質),兩者的著重點不太相同,看來很難用哪一邊取代另一邊。在 HasSwap
的情形,concept 會是比較好的解決方案,因為我們要的東西的確是那種「使用模式」,用 concept 表述相當自然(至於「語意的描述不夠完整」這個問題,不只 concept system 遇到麻煩,Design by Contract 也遇到相同問題),而《HasSwap
》最後也提到用 trait class 實作的缺陷。
--
可以試著實作 TR1 "4 Metaprogramming and type traits" 的所有內容,練習 TMP 技巧。不過有些可能要從編譯器層級直接支援?
嗯, 語意問題, 初淺看來, 像是選擇問題!
就好像動態語言跟靜態語言之差, 差在一個彈
性大, 一個語意安全!
像 C#/Java 那種需要 implements 式的語
法, 對 Python 之類的語言來說, 是多此一舉
但我覺得這也是它高明之處, 就因為需要 implements 所以彈性較小, 但也因此留
給實作者一個決定語意的空間
有相同的操作介面者, 不一定皆符合特定領域
的語義, 如果它們真的是可通用的概念, 就請
implements 來確定, 算是另一種選擇方案
當然, 這樣泛用性, 就小了一點點 ..
boost 有一個 concept_check library
用來模擬 concept 的支援, 其實 gcc 裡
面的 STL 似乎有用到: function_reuqires<>
雖然做法不難理解, 不過再怎麼說也比不上
直接支援來的簡單 XD
<< 回到主頁