標準模板函式庫(STL)Wiki:
對於構築集合處理的方式,.NET與STL思想上略有小小不同。
NET趨向物件導向想法(結合資料與操作成為一物件),將集合操作用函數以成員函數形式(member function)附屬在樣板容器之下,相當於在集合操作用函數中隱含(implicity)帶入自身參考。
.NET集合操作用函數無法直接帶入函數指標,而是要帶入委派(delegate),建立對應操作的委派的方式之一:
泛型容器在帶入元素型別T後,即變成一獨立的強型別,帶入的樣板委派Predicator<T>之中的T也須與泛型容器元素型別T一致,才能通過在編譯期的型別檢查,概念相當於
帶錯Predicate型別編譯器報錯:
正確的範例實作:
STL則是分離函數與容器,函數與容器之間以迭代器(Iterator)作為遍歷(Traversal)媒介,明確(explicity)帶入函數,概念上較貼近C語言的純函數工具;
cplusplus.com:
以find_if()來說,除了兩個InputIterator引數須限制在同一型別,集合操作的函數限制為UnaryPredicate,僅接受一元素引數並回傳布林值,倒是沒限定元素引數型別需要與容器型別一致,以下兩組UnaryPredicate皆能通過編譯並執行:
胡思亂想:UnaryPredicate無強型別檢查似乎給了一些彈性?比如記憶體多型解析?
同場加映Lambda寫法:
C#:
官網範例,陳述式Lambda(有{}叫做陳述式):
C++11,陳述式Only
後記1:STL Algorithm也能用在 Qt容器(QList)上
STL 將「在資料上執行的操作」與「要執行操作的資料分開」
對於構築集合處理的方式,.NET與STL思想上略有小小不同。
NET趨向物件導向想法(結合資料與操作成為一物件),將集合操作用函數以成員函數形式(member function)附屬在樣板容器之下,相當於在集合操作用函數中隱含(implicity)帶入自身參考。
.NET集合操作用函數無法直接帶入函數指標,而是要帶入委派(delegate),建立對應操作的委派的方式之一:
public struct Data { public int field1; public double field2; public Data(int f1,double f2) { field1 = f1; field2 = f2; } } // The Predicate function should be non-member static bool isField1Odd(Data data) { return (data.field1%2)==1; } // Define the Predicate<T> delegate. Predicate<Data> predicate = isField1Odd;
泛型容器在帶入元素型別T後,即變成一獨立的強型別,帶入的樣板委派Predicator<T>之中的T也須與泛型容器元素型別T一致,才能通過在編譯期的型別檢查,概念相當於
- 泛型容器:List<T1>與List<T2>是完全不同型別
- 委派:Predicate<T1>與Predicate<T2>也是不同型別
- 以List<T1>.Find(Predicate<T1>) 來說,Find()只接受Predicate<T1>作為引數,帶入Predicate<T2>會被視為錯誤型別遭到排除
帶錯Predicate型別編譯器報錯:
Predicate<Data2> predicate2 = isField1OddData2; //list.Find(predicate2);// cannot convert from 'System.Predicate<Rextester.Data2>' to 'System.Predicate<Rextester.Data>'
正確的範例實作:
public static void Main(string[] args) { List<data> list = new List<data>(); list.Add(new Data(4,2)); list.Add(new Data(3,4)); list.Add(new Data(8,6)); // Define the Predicate<t> delegate. Predicate<data> predicate = isField1Odd; Data found = list.Find(predicate); Console.WriteLine(found.field1); }
STL則是分離函數與容器,函數與容器之間以迭代器(Iterator)作為遍歷(Traversal)媒介,明確(explicity)帶入函數,概念上較貼近C語言的純函數工具;
cplusplus.com:
public static void Main(string[] args) template<class InputIterator, class UnaryPredicate> InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred) { while (first!=last) { if (pred(*first)) return first; ++first; } return last; }
以find_if()來說,除了兩個InputIterator引數須限制在同一型別,集合操作的函數限制為UnaryPredicate,僅接受一元素引數並回傳布林值,倒是沒限定元素引數型別需要與容器型別一致,以下兩組UnaryPredicate皆能通過編譯並執行:
bool IsOdd (int i) { return ((i%2)==1); } bool IsOddDouble(double i){ return (((int)i%2)==1); } std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd); it = std::find_if (myvector.begin(), myvector.end(), IsOddDouble);
胡思亂想:UnaryPredicate無強型別檢查似乎給了一些彈性?比如記憶體多型解析?
同場加映Lambda寫法:
C#:
官網範例,陳述式Lambda(有{}叫做陳述式):
found = list.Find(delegate(Data data) { return (data.field1%2)==1; });把delegate拿掉的陳述式寫法:
found = list.Find((Data data) => { return (data.field1%2)==1; });運算式寫法(無{},單行達成):
Predicate<Data> func = (Data data) => (data.field1%2)==1; found = list.Find(func); //way1 found = list.Find((Data data) => (data.field1%2)==1); //way2
C++11,陳述式Only
it = std::find_if (myvector.begin(), myvector.end(), [](int i){ return ((i%2)==1); });
後記1:STL Algorithm也能用在 Qt容器(QList)上
沒有留言:
張貼留言