2011-09-03 88 views
5

例如:爲什麼stl中的每個集合類型都沒有for_each成員函數?

v.for_each([](int i) { printf("%d\n", i); }); 

如果遠高於常用的更優雅和可讀性:

std::for_each(v.begin(), v.end(), [](int i) { printf("%d\n", i); }); 

是否有正當的理由這樣一個成員函數從標準缺失?

+0

爲什麼你會需要它?成員函數僅用於實現可以更高效的目的(set :: find比set上的std :: find()更有效)。哦,如果你想避免無處不在的'.begin()',en'.end()'調用,可以使用[Boost Range Algorithms](http://www.boost.org/doc/libs/1_47_0/libs/)範圍/ DOC/HTML /範圍/參考/算法/ introduction.html)。甜語法糖 – sehe

+0

@sehe:或* less *高效,像'std :: list :: sort()':-) –

+0

@Kerrek:'std :: list :: sort'是特殊的,'std :: sort'需要'RandomAccessIterator',所以它不能用於列表。 –

回答

8

這是爲整個庫的標準設計原理:從算法分開的容器中。

如果你做到了你的方式,你就必須實現對每個集裝箱Ÿ每一個功能X,導致你M * N個實現,如果你爲M的功能和N容器。

通過使用迭代器,使算法在迭代器而不是容器的工作,你只需要,實行M算法加N Iterator接口。

這種分離也意味着你必須應用的無限廣闊範圍:該算法不能僅僅被用於庫容器,但任何容器,現在還是將來,任何人都決定編寫和迭代器裝備。有限與無限重用是一個相當有力的論據!通過通用的免費界面調用算法不會增加任何成本。

+0

Mixin可以用來緩解這個問題 - 你可以編寫一個泛型函數mixin,它可以在任何容器上運行。 – Puppy

+0

@DeadMG:你將如何使用混合來爲每一個做一個正則表達式匹配或目錄遍歷的集合? –

+0

容器從mixin繼承,它使用引擎蓋下的迭代器來提供功能。只要對象提供迭代器 - 就像現在一樣 - 然後mixin可以使用OP中顯示的接口將該支持轉換爲簡單的成員函數。另外,它實際上是* more * generic,因爲如果你需要,例如'std :: list',你可以自己覆蓋容器類中的功能。 – Puppy

1

簡單的事實是,標準庫設計是從語言沒有提供許多功能的時候開始的,現在很多常見設計(如基於CRTP的mixin)都沒有提供。這意味着當創建標準庫時,現在顯而易見的卓越設計就無法實現或設計。

迭代做出了巨大的通用實現,但他們提出了一個蘇茨基通用接口。我覺得悲哀的是,而不是與庫設計解決問題和檢修的,相反,他們推出了一個特殊的情況下,語言功能的問題的一個很小的子集。

+0

您能否展示一個可以適應未來任何容器和未來算法的mixin的小例子? –

+0

@Kerrek:它不需要。我們可以使用現有的對未來算法的支持,未來的容器可以繼承它,我們可以爲最常用的算法獲得更好的結果。 – Puppy

+0

我明白了。那麼,提供這個很好。這樣的聲音可以作爲可選功能集添加... –

2
template <class InputIterator, class UnaryFunction> 
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f); 

正如你所看到的for_each需要輸入迭代器作爲參數,所以任何STL容器,可以提供輸入迭代器兼容(從輸入迭代意義之餘,也有可能是雙向的,隨機訪問迭代器等)會與std :: for_each兼容。通過這種方式設計,stl通用分離算法與數據類型(容器)相比更加優雅&通用。

0

爲什麼你會需要它?

如果可以使實現更高效(set :: find比set上的std :: find()更有效,那麼成員函數僅用於此目的。

PS哦,如果你想避免無處不.begin(),EN .end()電話,使用Boost Range Algorithms。甜語法糖

隨機升壓範圍啓發樣本:

#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 
#include <boost/pending/integer_range.hpp> 

using namespace boost::adaptors; 

static int mod7(int v) 
    { return v % 7; } 

int main() 
{ 
    std::vector<int> v; 

    boost::copy(
      boost::make_integer_range(1,100) | transformed(mod7), 
      std::back_inserter(v)); 

    boost::sort(v); 

    boost::copy(
      v | reversed | uniqued, 
      std::ostream_iterator<int>(std::cout, ", ")); 
} 
相關問題