2006/08/15

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 than std::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 後,tu 的值互換」之類的語意描述,不過我不知道 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 技巧。不過有些可能要從編譯器層級直接支援?

Anonymous Anonymous8/15/2006 6:53 pm 說:

嗯, 語意問題, 初淺看來, 像是選擇問題!

就好像動態語言跟靜態語言之差, 差在一個彈
性大, 一個語意安全!

像 C#/Java 那種需要 implements 式的語
法, 對 Python 之類的語言來說, 是多此一舉

但我覺得這也是它高明之處, 就因為需要 implements 所以彈性較小, 但也因此留
給實作者一個決定語意的空間

有相同的操作介面者, 不一定皆符合特定領域
的語義, 如果它們真的是可通用的概念, 就請
implements 來確定, 算是另一種選擇方案

當然, 這樣泛用性, 就小了一點點 ..

 
Anonymous Anonymous8/15/2006 7:02 pm 說:

boost 有一個 concept_check library
用來模擬 concept 的支援, 其實 gcc 裡
面的 STL 似乎有用到: function_reuqires<>

雖然做法不難理解, 不過再怎麼說也比不上
直接支援來的簡單 XD

 

<< 回到主頁