|  | /***************************************************************************** | 
|  |  | 
|  | Licensed to Accellera Systems Initiative Inc. (Accellera) under one or | 
|  | more contributor license agreements.  See the NOTICE file distributed | 
|  | with this work for additional information regarding copyright ownership. | 
|  | Accellera licenses this file to you under the Apache License, Version 2.0 | 
|  | (the "License"); you may not use this file except in compliance with the | 
|  | License.  You may obtain a copy of the License at | 
|  |  | 
|  | http://www.apache.org/licenses/LICENSE-2.0 | 
|  |  | 
|  | Unless required by applicable law or agreed to in writing, software | 
|  | distributed under the License is distributed on an "AS IS" BASIS, | 
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 
|  | implied.  See the License for the specific language governing | 
|  | permissions and limitations under the License. | 
|  |  | 
|  | *****************************************************************************/ | 
|  |  | 
|  | /* | 
|  | * Copyright 2018 Google, Inc. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions are | 
|  | * met: redistributions of source code must retain the above copyright | 
|  | * notice, this list of conditions and the following disclaimer; | 
|  | * redistributions in binary form must reproduce the above copyright | 
|  | * notice, this list of conditions and the following disclaimer in the | 
|  | * documentation and/or other materials provided with the distribution; | 
|  | * neither the name of the copyright holders nor the names of its | 
|  | * contributors may be used to endorse or promote products derived from | 
|  | * this software without specific prior written permission. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | #ifndef __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__ | 
|  | #define __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__ | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <exception> | 
|  | #include <iterator> | 
|  | #include <vector> | 
|  |  | 
|  | #include "../core/sc_module.hh" | 
|  | #include "../core/sc_object.hh" | 
|  | #include "messages.hh" | 
|  |  | 
|  | namespace sc_gem5 | 
|  | { | 
|  |  | 
|  | // Goop for supporting sc_vector_iter, simplified from the Accellera version. | 
|  |  | 
|  | #if __cplusplus >= 201103L | 
|  |  | 
|  | using std::enable_if; | 
|  | using std::remove_const; | 
|  | using std::is_same; | 
|  | using std::is_const; | 
|  |  | 
|  | #else | 
|  |  | 
|  | template<bool Cond, typename T=void> | 
|  | struct enable_if | 
|  | {}; | 
|  |  | 
|  | template<typename T> | 
|  | struct enable_if<true, T> | 
|  | { | 
|  | typedef T type; | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | struct remove_const | 
|  | { | 
|  | typedef T type; | 
|  | }; | 
|  | template <typename T> | 
|  | struct remove_const<const T> | 
|  | { | 
|  | typedef T type; | 
|  | }; | 
|  |  | 
|  | template <typename T, typename U> | 
|  | struct is_same | 
|  | { | 
|  | static const bool value = false; | 
|  | }; | 
|  | template <typename T> | 
|  | struct is_same<T, T> | 
|  | { | 
|  | static const bool value = true; | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | struct is_const | 
|  | { | 
|  | static const bool value = false; | 
|  | }; | 
|  | template <typename T> | 
|  | struct is_const<const T> | 
|  | { | 
|  | static const bool value = true; | 
|  | }; | 
|  |  | 
|  | #endif | 
|  |  | 
|  | template <typename CT, typename T> | 
|  | struct is_more_const | 
|  | { | 
|  | static const bool value = | 
|  | is_same<typename remove_const<CT>::type, | 
|  | typename remove_const<T>::type>::value && | 
|  | is_const<CT>::value >= is_const<T>::value; | 
|  | }; | 
|  |  | 
|  | struct special_result | 
|  | {}; | 
|  |  | 
|  | template <typename T> | 
|  | struct remove_special_fptr | 
|  | {}; | 
|  |  | 
|  | template <typename T> | 
|  | struct remove_special_fptr<special_result & (*)(T)> | 
|  | { | 
|  | typedef T type; | 
|  | }; | 
|  |  | 
|  | #define SC_RPTYPE_(Type) \ | 
|  | ::sc_gem5::remove_special_fptr< \ | 
|  | ::sc_gem5::special_result & (*) Type>::type::value | 
|  |  | 
|  | #define SC_ENABLE_IF_(Cond) \ | 
|  | typename ::sc_gem5::enable_if<SC_RPTYPE_(Cond)>::type * = NULL | 
|  |  | 
|  | } // namespace sc_gem5 | 
|  |  | 
|  | namespace sc_core | 
|  | { | 
|  |  | 
|  | template <typename T, typename MT> | 
|  | class sc_vector_assembly; | 
|  |  | 
|  | template <typename T> | 
|  | class sc_vector; | 
|  |  | 
|  | template <typename T, typename MT> | 
|  | sc_vector_assembly<T, MT> sc_assemble_vector( | 
|  | sc_vector<T> &, MT(T::* member_ptr)); | 
|  |  | 
|  | class sc_vector_base : public sc_object | 
|  | { | 
|  | public: | 
|  | typedef size_t size_type; | 
|  |  | 
|  | sc_vector_base(const char *_name) : sc_object(_name) {} | 
|  |  | 
|  | virtual const char *kind() const { return "sc_vector"; } | 
|  | size_type size() const; | 
|  | const std::vector<sc_object *> &get_elements() const; | 
|  |  | 
|  | protected: | 
|  | std::vector<void *> objs; | 
|  |  | 
|  | // What's returned by get_elements, which really returns the elemenets | 
|  | // which are also objects. | 
|  | mutable std::vector<sc_object *> elements; | 
|  |  | 
|  | sc_object *implicitCast(sc_object *p) const { return p; } | 
|  | sc_object *implicitCast(...) const | 
|  | { | 
|  | SC_REPORT_ERROR(SC_ID_VECTOR_NONOBJECT_ELEMENTS_, name()); | 
|  | return nullptr; | 
|  | } | 
|  | virtual sc_object *objectCast(void *) const = 0; | 
|  |  | 
|  | void checkIndex(size_type index) const; | 
|  | void forceParent() const; | 
|  | void unforceParent() const; | 
|  |  | 
|  | void reportEmpty(const char *kind_, bool empty_dest) const; | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Non-standard iterator access adapters. Without using these, the classes as | 
|  | * defined in the standard won't compile because of redundant bind() overloads. | 
|  | */ | 
|  |  | 
|  | template <typename Element> | 
|  | class sc_direct_access | 
|  | { | 
|  | public: | 
|  | typedef Element ElementType; | 
|  | typedef ElementType Type; | 
|  | typedef typename sc_gem5::remove_const<ElementType>::type PlainType; | 
|  |  | 
|  | typedef sc_direct_access<ElementType> Policy; | 
|  | typedef sc_direct_access<PlainType> NonConstPolicy; | 
|  | typedef sc_direct_access<const PlainType> ConstPolicy; | 
|  |  | 
|  | sc_direct_access() {} | 
|  | sc_direct_access(const NonConstPolicy &) {} | 
|  |  | 
|  | template <typename U> | 
|  | sc_direct_access(const U &, | 
|  | SC_ENABLE_IF_(( | 
|  | sc_gem5::is_more_const< | 
|  | ElementType, typename U::Policy::ElementType> | 
|  | )) | 
|  | ) | 
|  | {} | 
|  |  | 
|  | ElementType * | 
|  | get(ElementType *this_) const | 
|  | { | 
|  | return this_; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename Element, typename Access> | 
|  | class sc_member_access | 
|  | { | 
|  | public: | 
|  | template <typename, typename> | 
|  | friend class sc_member_access; | 
|  |  | 
|  | typedef Element ElementType; | 
|  | typedef Access AccessType; | 
|  | typedef AccessType (ElementType::*MemberType); | 
|  | typedef AccessType Type; | 
|  | typedef typename sc_gem5::remove_const<AccessType>::type PlainType; | 
|  | typedef typename sc_gem5::remove_const<ElementType>::type PlainElemType; | 
|  |  | 
|  | typedef sc_member_access<ElementType, AccessType> Policy; | 
|  | typedef sc_member_access<PlainElemType, PlainType> NonConstPolicy; | 
|  | typedef sc_member_access<const PlainElemType, const PlainType> ConstPolicy; | 
|  |  | 
|  | sc_member_access(MemberType ptr) : ptr_(ptr) {} | 
|  | sc_member_access(const NonConstPolicy &other) : ptr_(other.ptr_) {} | 
|  |  | 
|  | AccessType *get(ElementType *this_) const { return &(this_->*ptr_); } | 
|  |  | 
|  | private: | 
|  | MemberType ptr_; | 
|  | }; | 
|  |  | 
|  | template <typename Element, | 
|  | typename AccessPolicy=sc_direct_access<Element> > | 
|  | class sc_vector_iter : | 
|  | public std::iterator<std::random_access_iterator_tag, | 
|  | typename AccessPolicy::Type>, | 
|  | private AccessPolicy | 
|  | { | 
|  | private: | 
|  | typedef Element ElementType; | 
|  | typedef typename AccessPolicy::Policy Policy; | 
|  | typedef typename AccessPolicy::NonConstPolicy NonConstPolicy; | 
|  | typedef typename AccessPolicy::ConstPolicy ConstPolicy; | 
|  | typedef typename Policy::Type AccessType; | 
|  |  | 
|  | typedef typename sc_gem5::remove_const<ElementType>::type PlainType; | 
|  | typedef const PlainType ConstPlainType; | 
|  | typedef typename sc_direct_access<PlainType>::ConstPolicy | 
|  | ConstDirectPolicy; | 
|  |  | 
|  | friend class sc_vector<PlainType>; | 
|  | template <typename, typename> | 
|  | friend class sc_vector_assembly; | 
|  | template <typename, typename> | 
|  | friend class sc_vector_iter; | 
|  |  | 
|  | typedef std::iterator<std::random_access_iterator_tag, AccessType> | 
|  | BaseType; | 
|  | typedef sc_vector_iter ThisType; | 
|  | typedef sc_vector<PlainType> VectorType; | 
|  | typedef std::vector<void *> StorageType; | 
|  |  | 
|  | template <typename U> | 
|  | struct SelectIter | 
|  | { | 
|  | typedef typename std::vector<void *>::iterator type; | 
|  | }; | 
|  | template <typename U> | 
|  | struct SelectIter<const U> | 
|  | { | 
|  | typedef typename std::vector<void *>::const_iterator type; | 
|  | }; | 
|  | typedef typename SelectIter<ElementType>::type RawIterator; | 
|  | typedef sc_vector_iter<ConstPlainType, ConstPolicy> ConstIterator; | 
|  | typedef sc_vector_iter<ConstPlainType, ConstDirectPolicy> | 
|  | ConstDirectIterator; | 
|  |  | 
|  | RawIterator it_; | 
|  |  | 
|  | sc_vector_iter(RawIterator it, Policy acc=Policy()) : | 
|  | Policy(acc), it_(it) | 
|  | {} | 
|  |  | 
|  | Policy const &get_policy() const { return *this; } | 
|  |  | 
|  | public: | 
|  | // Conforms to Random Access Iterator category. | 
|  | // See ISO/IEC 14882:2003(E), 24.1 [lib.iterator.requirements] | 
|  |  | 
|  | typedef typename BaseType::difference_type difference_type; | 
|  | typedef typename BaseType::reference reference; | 
|  | typedef typename BaseType::pointer pointer; | 
|  |  | 
|  | sc_vector_iter() : Policy(), it_() {} | 
|  |  | 
|  | template <typename It> | 
|  | sc_vector_iter(const It &it, | 
|  | SC_ENABLE_IF_(( | 
|  | sc_gem5::is_more_const< | 
|  | ElementType, typename It::Policy::ElementType> | 
|  | )) | 
|  | ) : Policy(it.get_policy()), it_(it.it_) | 
|  | {} | 
|  |  | 
|  | ThisType & | 
|  | operator ++ () | 
|  | { | 
|  | ++it_; | 
|  | return *this; | 
|  | } | 
|  | ThisType & | 
|  | operator -- () | 
|  | { | 
|  | --it_; | 
|  | return *this; | 
|  | } | 
|  | ThisType | 
|  | operator ++ (int) | 
|  | { | 
|  | ThisType old(*this); | 
|  | ++it_; | 
|  | return old; | 
|  | } | 
|  | ThisType | 
|  | operator -- (int) | 
|  | { | 
|  | ThisType old(*this); | 
|  | --it_; | 
|  | return old; | 
|  | } | 
|  |  | 
|  | ThisType | 
|  | operator + (difference_type n) const | 
|  | { | 
|  | return ThisType(it_ + n, get_policy()); | 
|  | } | 
|  | ThisType | 
|  | operator - (difference_type n) const | 
|  | { | 
|  | return ThisType(it_ - n, get_policy()); | 
|  | } | 
|  |  | 
|  | ThisType & | 
|  | operator += (difference_type n) | 
|  | { | 
|  | it_ += n; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | ThisType & | 
|  | operator -= (difference_type n) | 
|  | { | 
|  | it_ -= n; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | bool | 
|  | operator == (const ConstDirectIterator &other) const | 
|  | { | 
|  | return it_ == other.it_; | 
|  | } | 
|  | bool | 
|  | operator != (const ConstDirectIterator &other) const | 
|  | { | 
|  | return it_ != other.it_; | 
|  | } | 
|  | bool | 
|  | operator <= (const ConstDirectIterator &other) const | 
|  | { | 
|  | return it_ <= other.it_; | 
|  | } | 
|  | bool | 
|  | operator >= (const ConstDirectIterator &other) const | 
|  | { | 
|  | return it_ >= other.it_; | 
|  | } | 
|  | bool | 
|  | operator < (const ConstDirectIterator &other) const | 
|  | { | 
|  | return it_ < other.it_; | 
|  | } | 
|  | bool | 
|  | operator > (const ConstDirectIterator &other) const | 
|  | { | 
|  | return it_ > other.it_; | 
|  | } | 
|  |  | 
|  | reference | 
|  | operator * () const | 
|  | { | 
|  | return *Policy::get(static_cast<ElementType *>((void *)*it_)); | 
|  | } | 
|  | pointer | 
|  | operator -> () const | 
|  | { | 
|  | return Policy::get(static_cast<ElementType *>((void *)*it_)); | 
|  | } | 
|  | reference | 
|  | operator [] (difference_type n) const | 
|  | { | 
|  | return *Policy::get(static_cast<ElementType *>((void *)it_[n])); | 
|  | } | 
|  |  | 
|  | difference_type | 
|  | operator - (ConstDirectIterator const &other) const | 
|  | { | 
|  | return it_ - other.it_; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | class sc_vector : public sc_vector_base | 
|  | { | 
|  | public: | 
|  | using sc_vector_base::size_type; | 
|  | typedef sc_vector_iter<T> iterator; | 
|  | typedef sc_vector_iter<const T> const_iterator; | 
|  |  | 
|  | sc_vector() : sc_vector_base(::sc_core::sc_gen_unique_name("vector")) {} | 
|  | explicit sc_vector(const char *_name) : sc_vector_base(_name) {} | 
|  | sc_vector(const char *_name, size_type _size) : sc_vector_base(_name) | 
|  | { | 
|  | init(_size); | 
|  | } | 
|  | template <typename Creator> | 
|  | sc_vector(const char *_name, size_type _size, Creator creator) : | 
|  | sc_vector_base(_name) | 
|  | { | 
|  | init(_size, creator); | 
|  | } | 
|  | virtual ~sc_vector() { clear(); } | 
|  |  | 
|  | void | 
|  | init(size_type _size) | 
|  | { | 
|  | init(_size, &sc_vector<T>::create_element); | 
|  | } | 
|  | static T * | 
|  | create_element(const char *_name, size_type index) | 
|  | { | 
|  | return new T(_name); | 
|  | } | 
|  |  | 
|  | template <typename Creator> | 
|  | void | 
|  | init(size_type _size, Creator creator) | 
|  | { | 
|  | forceParent(); | 
|  | try { | 
|  | for (size_type i = 0; i < _size; i++) { | 
|  | // XXX The name and scope of these objects needs to be handled | 
|  | // specially. | 
|  | T *p = creator(sc_gen_unique_name(basename()), i); | 
|  | objs.push_back(p); | 
|  | } | 
|  | } catch (...) { | 
|  | unforceParent(); | 
|  | clear(); | 
|  | throw; | 
|  | } | 
|  | unforceParent(); | 
|  | } | 
|  |  | 
|  | T &operator [] (size_type index) { return *static_cast<T *>(objs[index]); } | 
|  | const T & | 
|  | operator [] (size_type index) const | 
|  | { | 
|  | return *static_cast<const T *>(objs[index]); | 
|  | } | 
|  |  | 
|  | T & | 
|  | at(size_type index) | 
|  | { | 
|  | this->checkIndex(index); | 
|  | return *static_cast<T *>(objs[index]); | 
|  | } | 
|  | const T & | 
|  | at(size_type index) const | 
|  | { | 
|  | this->checkIndex(index); | 
|  | return *static_cast<const T *>(objs[index]); | 
|  | } | 
|  |  | 
|  | iterator begin() { return objs.begin(); } | 
|  | iterator end() { return objs.end(); } | 
|  | const_iterator begin() const { return objs.begin(); } | 
|  | const_iterator end() const { return objs.end(); } | 
|  | const_iterator cbegin() const { return objs.begin(); } | 
|  | const_iterator cend() const { return objs.end(); } | 
|  |  | 
|  | template <typename ContainerType, typename ArgumentType> | 
|  | iterator | 
|  | bind(sc_vector_assembly<ContainerType, ArgumentType> c) | 
|  | { | 
|  | return bind(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename BindableContainer> | 
|  | iterator | 
|  | bind(BindableContainer &c) | 
|  | { | 
|  | return bind(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename BindableIterator> | 
|  | iterator | 
|  | bind(BindableIterator first, BindableIterator last) | 
|  | { | 
|  | return bind(first, last, this->begin()); | 
|  | } | 
|  |  | 
|  | template <typename BindableIterator> | 
|  | iterator | 
|  | bind(BindableIterator first, BindableIterator last, iterator from) | 
|  | { | 
|  | if (!size() || from == end() || first == last) | 
|  | reportEmpty(kind(), from == end()); | 
|  |  | 
|  | while (from != end() && first != last) | 
|  | (*from++).bind(*first++); | 
|  | return from; | 
|  | } | 
|  |  | 
|  | template <typename ContainerType, typename ArgumentType> | 
|  | iterator | 
|  | operator () (sc_vector_assembly<ContainerType, ArgumentType> c) | 
|  | { | 
|  | return (*this)(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename ArgumentContainer> | 
|  | iterator | 
|  | operator () (ArgumentContainer &c) | 
|  | { | 
|  | return (*this)(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename ArgumentIterator> | 
|  | iterator | 
|  | operator () (ArgumentIterator first, ArgumentIterator last) | 
|  | { | 
|  | return (*this)(first, last, this->begin()); | 
|  | } | 
|  |  | 
|  | template <typename ArgumentIterator> | 
|  | iterator | 
|  | operator () (ArgumentIterator first, ArgumentIterator last, iterator from) | 
|  | { | 
|  | if (!size() || from == end() || first == last) | 
|  | reportEmpty(kind(), from == end()); | 
|  |  | 
|  | while (from != end() && first != last) | 
|  | (*from++)(*first++); | 
|  | return from; | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Disabled | 
|  | sc_vector(const sc_vector &); | 
|  | sc_vector &operator = (const sc_vector &); | 
|  |  | 
|  | void | 
|  | clear() | 
|  | { | 
|  | for (auto obj: objs) | 
|  | delete static_cast<T *>(obj); | 
|  | } | 
|  |  | 
|  | template <typename, typename> | 
|  | friend class sc_vector_assembly; | 
|  |  | 
|  | sc_object * | 
|  | objectCast(void *ptr) const | 
|  | { | 
|  | return implicitCast(static_cast<T *>(ptr)); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T, typename MT> | 
|  | class sc_vector_assembly | 
|  | { | 
|  | public: | 
|  | friend sc_vector_assembly<T, MT> sc_assemble_vector<>( | 
|  | sc_vector<T> &, MT (T::*)); | 
|  |  | 
|  | typedef size_t size_type; | 
|  | typedef sc_vector_iter<T, sc_member_access<T, MT> > iterator; | 
|  | typedef sc_vector_iter< | 
|  | const T, sc_member_access<const T, const MT> > const_iterator; | 
|  | typedef MT (T::*MemberType); | 
|  |  | 
|  | sc_vector_assembly(const sc_vector_assembly &other) : | 
|  | vec_(other.vec_), ptr_(other.ptr_) | 
|  | {} | 
|  |  | 
|  | iterator begin() { return iterator(vec_->begin().it_, ptr_); } | 
|  | iterator end() { return iterator(vec_->end().it_, ptr_); } | 
|  |  | 
|  | const_iterator | 
|  | cbegin() const | 
|  | { | 
|  | return const_iterator(vec_->begin().it_, ptr_); | 
|  | } | 
|  | const_iterator | 
|  | cend() const | 
|  | { | 
|  | return const_iterator(vec_->end().it_, ptr_); | 
|  | } | 
|  |  | 
|  | const_iterator | 
|  | begin() const | 
|  | { | 
|  | return const_iterator(vec_->begin().it_, ptr_); | 
|  | } | 
|  | const_iterator | 
|  | end() const | 
|  | { | 
|  | return const_iterator(vec_->end().it_, ptr_); | 
|  | } | 
|  |  | 
|  | size_type size() const { return vec_->size(); } | 
|  |  | 
|  | std::vector<sc_object *> | 
|  | get_elements() const | 
|  | { | 
|  | std::vector<sc_object *> ret; | 
|  | for (const_iterator it = begin(); it != end(); it++) { | 
|  | sc_object *obj_ptr = vec_->objectCast(const_cast<MT *>(&*it)); | 
|  |  | 
|  | if (obj_ptr) | 
|  | ret.push_back(obj_ptr); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | typename iterator::reference | 
|  | operator [] (size_type i) | 
|  | { | 
|  | return (*vec_)[i].*ptr_; | 
|  | } | 
|  | typename const_iterator::reference | 
|  | operator [] (size_type i) const | 
|  | { | 
|  | return (*vec_)[i].*ptr_; | 
|  | } | 
|  |  | 
|  | typename iterator::reference | 
|  | at(size_type i) | 
|  | { | 
|  | return vec_->at(i).*ptr_; | 
|  | } | 
|  | typename const_iterator::reference | 
|  | at(size_type i) const | 
|  | { | 
|  | return vec_->at(i).*ptr_; | 
|  | } | 
|  |  | 
|  | template <typename ContainerType, typename ArgumentType> | 
|  | iterator | 
|  | bind(sc_vector_assembly<ContainerType, ArgumentType> c) | 
|  | { | 
|  | return bind(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename BindableContainer> | 
|  | iterator | 
|  | bind(BindableContainer &c) | 
|  | { | 
|  | return bind(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename BindableIterator> | 
|  | iterator | 
|  | bind(BindableIterator first, BindableIterator last) | 
|  | { | 
|  | return bind(first, last, this->begin()); | 
|  | } | 
|  |  | 
|  | template <typename BindableIterator> | 
|  | iterator | 
|  | bind(BindableIterator first, BindableIterator last, iterator from) | 
|  | { | 
|  | if (!size() || from == end() || first == last) | 
|  | vec_->reportEmpty("sc_vector_assembly", from == end()); | 
|  |  | 
|  | while (from != end() && first != last) | 
|  | (*from++).bind(*first++); | 
|  | return from; | 
|  | } | 
|  |  | 
|  | template <typename BindableIterator> | 
|  | iterator | 
|  | bind(BindableIterator first, BindableIterator last, | 
|  | typename sc_vector<T>::iterator from) | 
|  | { | 
|  | return bind(first, last, iterator(from.it_, ptr_)); | 
|  | } | 
|  |  | 
|  | template <typename ContainerType, typename ArgumentType> | 
|  | iterator | 
|  | operator () (sc_vector_assembly<ContainerType, ArgumentType> c) | 
|  | { | 
|  | return (*this)(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename ArgumentContainer> | 
|  | iterator | 
|  | operator () (ArgumentContainer &c) | 
|  | { | 
|  | return (*this)(c.begin(), c.end()); | 
|  | } | 
|  |  | 
|  | template <typename ArgumentIterator> | 
|  | iterator | 
|  | operator () (ArgumentIterator first, ArgumentIterator last) | 
|  | { | 
|  | return (*this)(first, last, this->begin()); | 
|  | } | 
|  |  | 
|  | template <typename ArgumentIterator> | 
|  | iterator | 
|  | operator () (ArgumentIterator first, ArgumentIterator last, iterator from) | 
|  | { | 
|  | if (!size() || from == end() || first == last) | 
|  | vec_->reportEmpty("sc_vector_assembly", from == end()); | 
|  |  | 
|  | while (from != end() && first != last) | 
|  | (*from++)(*first++); | 
|  | return from; | 
|  | } | 
|  |  | 
|  | template <typename ArgumentIterator> | 
|  | iterator | 
|  | operator () (ArgumentIterator first, ArgumentIterator last, | 
|  | typename sc_vector<T>::iterator from) | 
|  | { | 
|  | return (*this)(first, last, iterator(from.it_, ptr_)); | 
|  | } | 
|  |  | 
|  | private: | 
|  | sc_vector_assembly(sc_vector<T> &v, MemberType ptr) : | 
|  | vec_(&v), ptr_(ptr) | 
|  | {} | 
|  |  | 
|  | sc_vector<T> *vec_; | 
|  | MemberType ptr_; | 
|  | }; | 
|  |  | 
|  | template <typename T, typename MT> | 
|  | sc_vector_assembly<T, MT> | 
|  | sc_assemble_vector(sc_vector<T> &v, MT (T::*ptr)) | 
|  | { | 
|  | return sc_vector_assembly<T, MT>(v, ptr); | 
|  | } | 
|  |  | 
|  | } // namespace sc_core | 
|  |  | 
|  | #endif  //__SYSTEMC_EXT_UTIL_SC_VECTOR_HH__ |