我有一些類,因各種原因離開這個討論的範圍,我不能修改(不相關的實施細節省略)進行迭代是我處理的很多類似的'Foo'和'Bar'類,它們都是從其他地方生成的代碼和我不想進行子類化的東西等等。)適應非可迭代的容器通過自定義模板化的迭代器
[編輯:澄清 - 儘管有很多類似'Foo'和'Bar'類,它保證每個「外部」類都有getter和size方法。只有getter方法名稱和返回類型對於每個「外部」纔會有所不同,這取決於它所包含的「內部」類型是什麼。
所以,如果我有巴茲其中包含QUUX情況下,會有QUUX &巴茲:: get_quux(爲size_t指數),併爲size_t巴茲:: size_quux()。]
鑑於酒吧類的設計,你不能輕易地在STL算法使用(例如for_each的,find_if等),而且必須做必要的循環,而不是採取功能性辦法(爲什麼我更喜歡後者的原因也超出範圍的討論):
Bar b;
size_t numFoo = b.size_foo();
for (int fooIdx = 0; fooIdx < numFoo; ++fooIdx) {
Foo& f = b.get_foo(fooIdx);
/* ... do stuff with 'f' ... */
}
所以...我從來沒有創建過自定義迭代器,並且在閱讀了關於SO的各種問題/答案後首先,自定義迭代器機制(注意:'function'和'bind'的所有用法都來自std :: tr1在MSVC9):
// Iterator mechanism...
template <typename TOuter, typename TInner>
class ContainerIterator : public std::iterator<std::input_iterator_tag, TInner> {
public:
typedef function<TInner& (size_t)> func_type;
ContainerIterator(const ContainerIterator& other) : mFunc(other.mFunc), mIndex(other.mIndex) {}
ContainerIterator& operator++() { ++mIndex; return *this; }
bool operator==(const ContainerIterator& other) {
return ((mFunc.target<TOuter>() == other.mFunc.target<TOuter>()) && (mIndex == other.mIndex));
}
bool operator!=(const ContainerIterator& other) { return !(*this == other); }
TInner& operator*() { return mFunc(mIndex); }
private:
template<typename TOuter, typename TInner>
friend class ContainerProxy;
ContainerIterator(func_type func, size_t index = 0) : mFunc(func), mIndex(index) {}
function<TInner& (size_t)> mFunc;
size_t mIndex;
};
接着,通過我得到的機制代表開始和內部容器的端部有效迭代:
:// Proxy(?) to the outer class instance, providing a way to get begin() and end()
// iterators to the inner contained instances...
template <typename TOuter, typename TInner>
class ContainerProxy {
public:
typedef function<TInner& (size_t)> access_func_type;
typedef function<size_t()> size_func_type;
typedef ContainerIterator<TOuter, TInner> iter_type;
ContainerProxy(access_func_type accessFunc, size_func_type sizeFunc) : mAccessFunc(accessFunc), mSizeFunc(sizeFunc) {}
iter_type begin() const {
size_t numItems = mSizeFunc();
if (0 == numItems) return end();
else return ContainerIterator<TOuter, TInner>(mAccessFunc, 0);
}
iter_type end() const {
size_t numItems = mSizeFunc();
return ContainerIterator<TOuter, TInner>(mAccessFunc, numItems);
}
private:
access_func_type mAccessFunc;
size_func_type mSizeFunc;
};
我可以以下列方式使用這些類
// Sample function object for taking action on an LMX inner class instance yielded
// by iteration...
template <typename TInner>
class SomeTInnerFunctor {
public:
void operator()(const TInner& inner) {
/* ... whatever ... */
}
};
// Example of iterating over an outer class instance's inner container...
Bar b; /* assume populated which contained items ... */
ContainerProxy<Bar, Foo> bProxy(
bind(&Bar::get_foo, b, _1),
bind(&Bar::size_foo, b));
for_each(bProxy.begin(), bProxy.end(), SomeTInnerFunctor<Foo>());
根據經驗,這種解決方案的功能正常(減去任何複製/粘貼或錯別字我可能已經編輯以上爲簡潔時引入的)。
所以,最後,實際的問題:
我不喜歡需要使用綁定的()和_1佔位符,等等調用者。所有他們真正關心的是:外型,內型,外類型的獲取內部實例方法,外部類型的獲取數內實例方法。
有什麼辦法來「隱藏」在某種程度上的模板類的身體的綁定?我一直無法找到一個方法來分別提供的類型和單獨內方法的模板參數...
謝謝!
David
如果你只是想要避免'std :: bind'和'std :: placeholders',你可以濫用這個事實,例如, 'stoo :: function'非常樂意吞噬指向成員函數的類型'Foo&(Bar :: *)(size_t)' –
Managu