component_iterator実装の続き。
BOOST_FOREACHに回せるように少しコードを追加。
だがまだ不完全である。
ソースコード
#pragma once /* ============================================================================== This file is part of the S.F.Tracker Copyright 2005-7 by Satoshi Fujiwara. S.F.Tracker can be redistributed and/or modified under the terms of the GNU General Public License, as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. S.F.Tracker is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with S.F.Tracker; if not, visit www.gnu.org/licenses or write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ============================================================================== */ /** @file * @author S.F. (Satoshi Fujiwara) * @brief Component を iterateしたり、rangeしたりするhelper class library. */ #include <boost/iterator_adaptors.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_base_and_derived.hpp> #include <boost/utility/enable_if.hpp> #include "src\juce_WithoutMacros.h" #include <boost/foreach.hpp> namespace sf { /** child component iteration */ template <typename ComponentType> struct component_iterator_base : public boost::iterator_facade<component_iterator_base<ComponentType>,ComponentType*,boost::random_access_traversal_tag> { private: struct enabler {}; public: template <class OtherValue> component_iterator_base( component_iterator_base<OtherValue> const& other , typename boost::enable_if< boost::is_convertible<OtherValue*,ComponentType*> , enabler >::type = enabler() ) : comp_(other.comp_),index_(other.index_){} explicit component_iterator_base<ComponentType>(ComponentType& comp,int index = 0) : comp_(&comp),index_(index) { }; private: component_iterator_base<ComponentType>() :comp_(0),index_(0){}; friend struct component_iterator_base; friend class boost::iterator_core_access; void increment() { if(index_ < (comp_->getNumChildComponents())) { ++index_; } }; void decrement() { if(index_ >= 0) { --index_; } } template <typename OtherType> bool equal( component_iterator_base<OtherType> const & other) const { if((index_ >= 0 && index_ < comp_->getNumChildComponents()) && (other.index_ >= 0 && other.index_ < other.comp_->getNumChildComponents())){ return comp_->getChildComponent(index_) == other.comp_->getChildComponent(other.index_); } else { return index_ == other.index_; } } reference dereference() const { Component* t = comp_->getChildComponent(index_); return t; }; void advance(difference_type n) { index_ += n; // valid_ = (index_ < comp_->getNumChildComponents() - 1) && (index_ > 0); }; difference_type distance_to (component_iterator_base const& other) const { return other.index_ - index_; } mutable int index_; mutable ComponentType* comp_; }; typedef component_iterator_base<Component> component_iterator; typedef component_iterator_base<Component const> const_component_iterator; //template <typename ComponentType > // inline component_iterator_base<ComponentType> begin(ComponentType& parent_comp) // { return component_iterator_base<ComponentType>(parent_comp);}; //template <typename ComponentType > // inline component_iterator_base<ComponentType> end(ComponentType& parent_comp) // { return component_iterator_base<ComponentType>(parent_comp,parent_comp.getNumChildComponents());}; inline sf::component_iterator begin(Component & parent_comp) { return sf::component_iterator(parent_comp);}; inline sf::component_iterator end(Component & parent_comp) { return sf::component_iterator(parent_comp,parent_comp.getNumChildComponents());}; inline sf::const_component_iterator begin(Component const & parent_comp) { return sf::const_component_iterator(parent_comp);}; inline sf::const_component_iterator end(Component const & parent_comp) { return sf::const_component_iterator(parent_comp,parent_comp.getNumChildComponents());}; } namespace juce { inline sf::component_iterator boost_range_begin(Component& parent_comp) { return sf::begin(parent_comp);}; inline sf::component_iterator boost_range_end(Component& parent_comp) { return sf::end(parent_comp);}; inline sf::const_component_iterator boost_range_begin(Component const & parent_comp) { return sf::begin(parent_comp);}; inline sf::const_component_iterator boost_range_end(Component const & parent_comp) { return sf::end(parent_comp);}; } namespace boost { // specialize rannge_iterator and range_const_iterator in namespace boost template<class ComponentType> struct range_iterator< typename boost::lazy_enable_if< boost::is_base_and_derived< juce::Component,ComponentType > , ComponentType > > { typedef sf::component_iterator_base<ComponentType> type; }; //specialize rannge_iterator and range_const_iterator in namespace boost template<> struct range_iterator<juce::Component> { typedef sf::component_iterator type; }; template<> struct range_const_iterator< juce::Component> { typedef sf::const_component_iterator type; }; namespace foreach { template<> struct is_noncopyable< juce::Component > : mpl::true_ { }; } }テストコード
#include "StdAfxtest.h" #include <boost/test/unit_test.hpp> #include "component_iterator_test.h" #include "../sftrackermain/component_iterator.h" using namespace boost::unit_test; using namespace sf; void component_iterator_test1() { TextButton btn(_T("button1")); for(int i = 0;i < 10;++i){ btn.addChildComponent(new TextButton((format(_T("button %d")) % i).str().c_str())); } { int i = 0; // forward++ Test for(component_iterator it = begin(btn),it_e = end(btn);it != it_e;++it) { // std::cout << (const TCHAR*)((*it)->getName()) << std::endl; BOOST_CHECK((*it)->getName() == btn.getChildComponent(i)->getName()); ++i; } // [] Operator Test component_iterator it = begin(btn); for(i = btn.getNumChildComponents() - 1 ;i >= 0; --i) { BOOST_CHECK((*it[i]).getName() == btn.getChildComponent(i)->getName()); } i = 0; Component* pc = &btn; BOOST_FOREACH(Component *p , static_cast<Component&>(btn)) { BOOST_CHECK(p->getName() == btn.getChildComponent(i++)->getName()); } } } test_suite* component_iterator_test() { test_suite* test_ BOOST_TEST_SUITE("coomponent_iterator_test"); test_->add(BOOST_TEST_CASE(&component_iterator_test1)); return test_; }