sc_vector.hh revision 13271
113271Sgabeblack@google.com/*****************************************************************************
213271Sgabeblack@google.com
313271Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413271Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513271Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613271Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713271Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813271Sgabeblack@google.com  License.  You may obtain a copy of the License at
913271Sgabeblack@google.com
1013271Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113271Sgabeblack@google.com
1213271Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313271Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413271Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513271Sgabeblack@google.com  implied.  See the License for the specific language governing
1613271Sgabeblack@google.com  permissions and limitations under the License.
1713271Sgabeblack@google.com
1813271Sgabeblack@google.com *****************************************************************************/
1913271Sgabeblack@google.com
2012852Sgabeblack@google.com/*
2112852Sgabeblack@google.com * Copyright 2018 Google, Inc.
2212852Sgabeblack@google.com *
2312852Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
2412852Sgabeblack@google.com * modification, are permitted provided that the following conditions are
2512852Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
2612852Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
2712852Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
2812852Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2912852Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
3012852Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
3112852Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
3212852Sgabeblack@google.com * this software without specific prior written permission.
3312852Sgabeblack@google.com *
3412852Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3512852Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3612852Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3712852Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3812852Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3912852Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4012852Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4112852Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4212852Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4312852Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4412852Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4512852Sgabeblack@google.com *
4612852Sgabeblack@google.com * Authors: Gabe Black
4712852Sgabeblack@google.com */
4812852Sgabeblack@google.com
4912852Sgabeblack@google.com#ifndef __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
5012852Sgabeblack@google.com#define __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
5112852Sgabeblack@google.com
5212852Sgabeblack@google.com#include <stdint.h>
5312852Sgabeblack@google.com
5412852Sgabeblack@google.com#include <exception>
5512872Sgabeblack@google.com#include <iterator>
5612852Sgabeblack@google.com#include <vector>
5712852Sgabeblack@google.com
5813271Sgabeblack@google.com#include "../core/sc_module.hh"
5912852Sgabeblack@google.com#include "../core/sc_object.hh"
6012852Sgabeblack@google.com
6112872Sgabeblack@google.comnamespace sc_gem5
6212872Sgabeblack@google.com{
6312872Sgabeblack@google.com
6412872Sgabeblack@google.com// Goop for supporting sc_vector_iter, simplified from the Accellera version.
6512872Sgabeblack@google.com
6612872Sgabeblack@google.com#if __cplusplus >= 201103L
6712872Sgabeblack@google.com
6812872Sgabeblack@google.comusing std::enable_if;
6912872Sgabeblack@google.comusing std::remove_const;
7012872Sgabeblack@google.comusing std::is_same;
7112872Sgabeblack@google.comusing std::is_const;
7212872Sgabeblack@google.com
7312872Sgabeblack@google.com#else
7412872Sgabeblack@google.com
7512872Sgabeblack@google.comtemplate<bool Cond, typename T=void>
7612872Sgabeblack@google.comstruct enable_if
7712872Sgabeblack@google.com{};
7812872Sgabeblack@google.com
7912872Sgabeblack@google.comtemplate<typename T>
8012872Sgabeblack@google.comstruct enable_if<true, T>
8112872Sgabeblack@google.com{
8212872Sgabeblack@google.com    typedef T type;
8312872Sgabeblack@google.com};
8412872Sgabeblack@google.com
8512872Sgabeblack@google.comtemplate <typename T>
8612872Sgabeblack@google.comstruct remove_const
8712872Sgabeblack@google.com{
8812872Sgabeblack@google.com    typedef T type;
8912872Sgabeblack@google.com};
9012872Sgabeblack@google.comtemplate <typename T>
9112872Sgabeblack@google.comstruct remove_const<const T>
9212872Sgabeblack@google.com{
9312872Sgabeblack@google.com    typedef T type;
9412872Sgabeblack@google.com};
9512872Sgabeblack@google.com
9612872Sgabeblack@google.comtemplate <typename T, typename U>
9712872Sgabeblack@google.comstruct is_same
9812872Sgabeblack@google.com{
9912872Sgabeblack@google.com    static const bool value = false;
10012872Sgabeblack@google.com};
10112872Sgabeblack@google.comtemplate <typename T>
10212872Sgabeblack@google.comstruct is_same<T, T>
10312872Sgabeblack@google.com{
10412872Sgabeblack@google.com    static const bool value = true;
10512872Sgabeblack@google.com};
10612872Sgabeblack@google.com
10712872Sgabeblack@google.comtemplate <typename T>
10812872Sgabeblack@google.comstruct is_const
10912872Sgabeblack@google.com{
11012872Sgabeblack@google.com    static const bool value = false;
11112872Sgabeblack@google.com};
11212872Sgabeblack@google.comtemplate <typename T>
11312872Sgabeblack@google.comstruct is_const<const T>
11412872Sgabeblack@google.com{
11512872Sgabeblack@google.com    static const bool value = true;
11612872Sgabeblack@google.com};
11712872Sgabeblack@google.com
11812872Sgabeblack@google.com#endif
11912872Sgabeblack@google.com
12012872Sgabeblack@google.comtemplate <typename CT, typename T>
12112872Sgabeblack@google.comstruct is_more_const
12212872Sgabeblack@google.com{
12312872Sgabeblack@google.com    static const bool value =
12412872Sgabeblack@google.com        is_same<typename remove_const<CT>::type,
12512872Sgabeblack@google.com                typename remove_const<T>::type>::value &&
12612872Sgabeblack@google.com        is_const<CT>::value >= is_const<T>::value;
12712872Sgabeblack@google.com};
12812872Sgabeblack@google.com
12912872Sgabeblack@google.comstruct special_result
13012872Sgabeblack@google.com{};
13112872Sgabeblack@google.com
13212872Sgabeblack@google.comtemplate <typename T>
13312872Sgabeblack@google.comstruct remove_special_fptr
13412872Sgabeblack@google.com{};
13512872Sgabeblack@google.com
13612872Sgabeblack@google.comtemplate <typename T>
13712872Sgabeblack@google.comstruct remove_special_fptr<special_result & (*)(T)>
13812872Sgabeblack@google.com{
13912872Sgabeblack@google.com    typedef T type;
14012872Sgabeblack@google.com};
14112872Sgabeblack@google.com
14212872Sgabeblack@google.com#define SC_RPTYPE_(Type) \
14312872Sgabeblack@google.com    ::sc_gem5::remove_special_fptr< \
14412872Sgabeblack@google.com        ::sc_gem5::special_result & (*) Type>::type::value
14512872Sgabeblack@google.com
14612872Sgabeblack@google.com#define SC_ENABLE_IF_(Cond) \
14712872Sgabeblack@google.com    typename ::sc_gem5::enable_if<SC_RPTYPE_(Cond)>::type * = NULL
14812872Sgabeblack@google.com
14912872Sgabeblack@google.com} // namespace sc_gem5
15012872Sgabeblack@google.com
15112852Sgabeblack@google.comnamespace sc_core
15212852Sgabeblack@google.com{
15312852Sgabeblack@google.com
15412852Sgabeblack@google.comtemplate <typename T, typename MT>
15512852Sgabeblack@google.comclass sc_vector_assembly;
15612852Sgabeblack@google.com
15712852Sgabeblack@google.comtemplate <typename T>
15812852Sgabeblack@google.comclass sc_vector;
15912852Sgabeblack@google.com
16012852Sgabeblack@google.comtemplate <typename T, typename MT>
16112852Sgabeblack@google.comsc_vector_assembly<T, MT> sc_assemble_vector(
16212852Sgabeblack@google.com        sc_vector<T> &, MT(T::* member_ptr));
16312852Sgabeblack@google.com
16412852Sgabeblack@google.comclass sc_vector_base : public sc_object
16512852Sgabeblack@google.com{
16612852Sgabeblack@google.com  public:
16712852Sgabeblack@google.com    typedef size_t size_type;
16812852Sgabeblack@google.com
16913271Sgabeblack@google.com    sc_vector_base(const char *_name) : sc_object(_name) {}
17013271Sgabeblack@google.com
17112852Sgabeblack@google.com    virtual const char *kind() const { return "sc_vector"; }
17212852Sgabeblack@google.com    size_type size() const;
17312852Sgabeblack@google.com    const std::vector<sc_object *> &get_elements() const;
17413271Sgabeblack@google.com
17513271Sgabeblack@google.com  protected:
17613271Sgabeblack@google.com    std::vector<void *> objs;
17713271Sgabeblack@google.com
17813271Sgabeblack@google.com    // What's returned by get_elements, which really returns the elemenets
17913271Sgabeblack@google.com    // which are also objects.
18013271Sgabeblack@google.com    mutable std::vector<sc_object *> elements;
18113271Sgabeblack@google.com
18213271Sgabeblack@google.com    sc_object *implicitCast(sc_object *p) const { return p; }
18313271Sgabeblack@google.com    sc_object *implicitCast(...) const
18413271Sgabeblack@google.com    {
18513271Sgabeblack@google.com        SC_REPORT_ERROR(
18613271Sgabeblack@google.com                "(E808) sc_vector::get_elements called for element type "
18713271Sgabeblack@google.com                "not derived from sc_object", name());
18813271Sgabeblack@google.com        return nullptr;
18913271Sgabeblack@google.com    }
19013271Sgabeblack@google.com    virtual sc_object *objectCast(void *) const = 0;
19113271Sgabeblack@google.com
19213271Sgabeblack@google.com    void checkIndex(size_type index) const;
19313271Sgabeblack@google.com    void forceParent() const;
19413271Sgabeblack@google.com    void unforceParent() const;
19513271Sgabeblack@google.com
19613271Sgabeblack@google.com    void reportEmpty(const char *kind_, bool empty_dest) const;
19712852Sgabeblack@google.com};
19812852Sgabeblack@google.com
19912872Sgabeblack@google.com
20012872Sgabeblack@google.com/*
20112872Sgabeblack@google.com * Non-standard iterator access adapters. Without using these, the classes as
20212872Sgabeblack@google.com * defined in the standard won't compile because of redundant bind() overloads.
20312872Sgabeblack@google.com */
20412872Sgabeblack@google.com
20512872Sgabeblack@google.comtemplate <typename Element>
20612872Sgabeblack@google.comclass sc_direct_access
20712872Sgabeblack@google.com{
20812872Sgabeblack@google.com  public:
20912872Sgabeblack@google.com    typedef Element ElementType;
21012872Sgabeblack@google.com    typedef ElementType Type;
21112872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
21212872Sgabeblack@google.com
21312872Sgabeblack@google.com    typedef sc_direct_access<ElementType> Policy;
21412872Sgabeblack@google.com    typedef sc_direct_access<PlainType> NonConstPolicy;
21512872Sgabeblack@google.com    typedef sc_direct_access<const PlainType> ConstPolicy;
21612872Sgabeblack@google.com
21712872Sgabeblack@google.com    sc_direct_access() {}
21812872Sgabeblack@google.com    sc_direct_access(const NonConstPolicy &) {}
21912872Sgabeblack@google.com
22012872Sgabeblack@google.com    template <typename U>
22112872Sgabeblack@google.com    sc_direct_access(const U &,
22212872Sgabeblack@google.com        SC_ENABLE_IF_((
22312872Sgabeblack@google.com            sc_gem5::is_more_const<
22412872Sgabeblack@google.com                    ElementType, typename U::Policy::ElementType>
22512872Sgabeblack@google.com        ))
22612872Sgabeblack@google.com    )
22712872Sgabeblack@google.com    {}
22812872Sgabeblack@google.com
22912872Sgabeblack@google.com    ElementType *
23012872Sgabeblack@google.com    get(ElementType *this_) const
23112872Sgabeblack@google.com    {
23212872Sgabeblack@google.com        return this_;
23312872Sgabeblack@google.com    }
23412872Sgabeblack@google.com};
23512872Sgabeblack@google.com
23612872Sgabeblack@google.comtemplate <typename Element, typename Access>
23712872Sgabeblack@google.comclass sc_member_access
23812872Sgabeblack@google.com{
23912872Sgabeblack@google.com  public:
24012872Sgabeblack@google.com    template <typename, typename>
24112872Sgabeblack@google.com    friend class sc_member_access;
24212872Sgabeblack@google.com
24312872Sgabeblack@google.com    typedef Element ElementType;
24412872Sgabeblack@google.com    typedef Access AccessType;
24512872Sgabeblack@google.com    typedef AccessType (ElementType::*MemberType);
24612872Sgabeblack@google.com    typedef AccessType Type;
24712872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<AccessType>::type PlainType;
24812872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<ElementType>::type PlainElemType;
24912872Sgabeblack@google.com
25012872Sgabeblack@google.com    typedef sc_member_access<ElementType, AccessType> Policy;
25112872Sgabeblack@google.com    typedef sc_member_access<PlainElemType, PlainType> NonConstPolicy;
25212872Sgabeblack@google.com    typedef sc_member_access<const PlainElemType, const PlainType> ConstPolicy;
25312872Sgabeblack@google.com
25412872Sgabeblack@google.com    sc_member_access(MemberType ptr) : ptr_(ptr) {}
25512872Sgabeblack@google.com    sc_member_access(const NonConstPolicy &other) : ptr_(other.ptr_) {}
25612872Sgabeblack@google.com
25712872Sgabeblack@google.com    AccessType *get(ElementType *this_) const { return &(this_->*ptr_); }
25812872Sgabeblack@google.com
25912872Sgabeblack@google.com  private:
26012872Sgabeblack@google.com    MemberType ptr_;
26112872Sgabeblack@google.com};
26212872Sgabeblack@google.com
26312872Sgabeblack@google.comtemplate <typename Element,
26412872Sgabeblack@google.com          typename AccessPolicy=sc_direct_access<Element> >
26512852Sgabeblack@google.comclass sc_vector_iter :
26612872Sgabeblack@google.com        public std::iterator<std::random_access_iterator_tag,
26712872Sgabeblack@google.com                             typename AccessPolicy::Type>,
26812872Sgabeblack@google.com        private AccessPolicy
26912852Sgabeblack@google.com{
27012872Sgabeblack@google.com  private:
27112872Sgabeblack@google.com    typedef Element ElementType;
27212872Sgabeblack@google.com    typedef typename AccessPolicy::Policy Policy;
27312872Sgabeblack@google.com    typedef typename AccessPolicy::NonConstPolicy NonConstPolicy;
27412872Sgabeblack@google.com    typedef typename AccessPolicy::ConstPolicy ConstPolicy;
27512872Sgabeblack@google.com    typedef typename Policy::Type AccessType;
27612872Sgabeblack@google.com
27712872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
27812872Sgabeblack@google.com    typedef const PlainType ConstPlainType;
27912872Sgabeblack@google.com    typedef typename sc_direct_access<PlainType>::ConstPolicy
28012872Sgabeblack@google.com        ConstDirectPolicy;
28112872Sgabeblack@google.com
28212872Sgabeblack@google.com    friend class sc_vector<PlainType>;
28312872Sgabeblack@google.com    template <typename, typename>
28412872Sgabeblack@google.com    friend class sc_vector_assembly;
28512872Sgabeblack@google.com    template <typename, typename>
28612872Sgabeblack@google.com    friend class sc_vector_iter;
28712872Sgabeblack@google.com
28812872Sgabeblack@google.com    typedef std::iterator<std::random_access_iterator_tag, AccessType>
28912872Sgabeblack@google.com        BaseType;
29012872Sgabeblack@google.com    typedef sc_vector_iter ThisType;
29112872Sgabeblack@google.com    typedef sc_vector<PlainType> VectorType;
29212872Sgabeblack@google.com    typedef std::vector<void *> StorageType;
29312872Sgabeblack@google.com
29412872Sgabeblack@google.com    template <typename U>
29512872Sgabeblack@google.com    struct SelectIter
29612872Sgabeblack@google.com    {
29712872Sgabeblack@google.com        typedef typename std::vector<void *>::iterator type;
29812872Sgabeblack@google.com    };
29912872Sgabeblack@google.com    template <typename U>
30012872Sgabeblack@google.com    struct SelectIter<const U>
30112872Sgabeblack@google.com    {
30212872Sgabeblack@google.com        typedef typename std::vector<void *>::const_iterator type;
30312872Sgabeblack@google.com    };
30412872Sgabeblack@google.com    typedef typename SelectIter<ElementType>::type RawIterator;
30512872Sgabeblack@google.com    typedef sc_vector_iter<ConstPlainType, ConstPolicy> ConstIterator;
30612872Sgabeblack@google.com    typedef sc_vector_iter<ConstPlainType, ConstDirectPolicy>
30712872Sgabeblack@google.com        ConstDirectIterator;
30812872Sgabeblack@google.com
30912872Sgabeblack@google.com    RawIterator it_;
31012872Sgabeblack@google.com
31112872Sgabeblack@google.com    sc_vector_iter(RawIterator it, Policy acc=Policy()) :
31212872Sgabeblack@google.com        Policy(acc), it_(it)
31312872Sgabeblack@google.com    {}
31412872Sgabeblack@google.com
31512872Sgabeblack@google.com    Policy const &get_policy() const { return *this; }
31612872Sgabeblack@google.com
31712872Sgabeblack@google.com  public:
31812852Sgabeblack@google.com    // Conforms to Random Access Iterator category.
31912852Sgabeblack@google.com    // See ISO/IEC 14882:2003(E), 24.1 [lib.iterator.requirements]
32012852Sgabeblack@google.com
32112872Sgabeblack@google.com    typedef typename BaseType::difference_type difference_type;
32212872Sgabeblack@google.com    typedef typename BaseType::reference reference;
32312872Sgabeblack@google.com    typedef typename BaseType::pointer pointer;
32412872Sgabeblack@google.com
32512872Sgabeblack@google.com    sc_vector_iter() : Policy(), it_() {}
32612872Sgabeblack@google.com
32712872Sgabeblack@google.com    template <typename It>
32812872Sgabeblack@google.com    sc_vector_iter(const It &it,
32912872Sgabeblack@google.com        SC_ENABLE_IF_((
33012872Sgabeblack@google.com            sc_gem5::is_more_const<
33112872Sgabeblack@google.com                ElementType, typename It::Policy::ElementType>
33212872Sgabeblack@google.com        ))
33312872Sgabeblack@google.com    ) : Policy(it.get_policy()), it_(it.it_)
33412872Sgabeblack@google.com    {}
33512872Sgabeblack@google.com
33612872Sgabeblack@google.com    ThisType &
33712872Sgabeblack@google.com    operator ++ ()
33812872Sgabeblack@google.com    {
33912872Sgabeblack@google.com        ++it_;
34012872Sgabeblack@google.com        return *this;
34112872Sgabeblack@google.com    }
34212872Sgabeblack@google.com    ThisType &
34312872Sgabeblack@google.com    operator -- ()
34412872Sgabeblack@google.com    {
34512872Sgabeblack@google.com        --it_;
34612872Sgabeblack@google.com        return *this;
34712872Sgabeblack@google.com    }
34812872Sgabeblack@google.com    ThisType
34912872Sgabeblack@google.com    operator ++ (int)
35012872Sgabeblack@google.com    {
35112872Sgabeblack@google.com        ThisType old(*this);
35212872Sgabeblack@google.com        ++it_;
35312872Sgabeblack@google.com        return old;
35412872Sgabeblack@google.com    }
35512872Sgabeblack@google.com    ThisType
35612872Sgabeblack@google.com    operator -- (int)
35712872Sgabeblack@google.com    {
35812872Sgabeblack@google.com        ThisType old(*this);
35912872Sgabeblack@google.com        --it_;
36012872Sgabeblack@google.com        return old;
36112872Sgabeblack@google.com    }
36212872Sgabeblack@google.com
36312872Sgabeblack@google.com    ThisType
36412872Sgabeblack@google.com    operator + (difference_type n) const
36512872Sgabeblack@google.com    {
36612872Sgabeblack@google.com        return ThisType(it_ + n, get_policy());
36712872Sgabeblack@google.com    }
36812872Sgabeblack@google.com    ThisType
36912872Sgabeblack@google.com    operator - (difference_type n) const
37012872Sgabeblack@google.com    {
37112872Sgabeblack@google.com        return ThisType(it_ - n, get_policy());
37212872Sgabeblack@google.com    }
37312872Sgabeblack@google.com
37412872Sgabeblack@google.com    ThisType &
37512872Sgabeblack@google.com    operator += (difference_type n)
37612872Sgabeblack@google.com    {
37712872Sgabeblack@google.com        it_ += n;
37812872Sgabeblack@google.com        return *this;
37912872Sgabeblack@google.com    }
38012872Sgabeblack@google.com
38112872Sgabeblack@google.com    ThisType &
38212872Sgabeblack@google.com    operator -= (difference_type n)
38312872Sgabeblack@google.com    {
38412872Sgabeblack@google.com        it_ -= n;
38512872Sgabeblack@google.com        return *this;
38612872Sgabeblack@google.com    }
38712872Sgabeblack@google.com
38812872Sgabeblack@google.com    bool
38912872Sgabeblack@google.com    operator == (const ConstDirectIterator &other) const
39012872Sgabeblack@google.com    {
39112872Sgabeblack@google.com        return it_ == other.it_;
39212872Sgabeblack@google.com    }
39312872Sgabeblack@google.com    bool
39412872Sgabeblack@google.com    operator != (const ConstDirectIterator &other) const
39512872Sgabeblack@google.com    {
39612872Sgabeblack@google.com        return it_ != other.it_;
39712872Sgabeblack@google.com    }
39812872Sgabeblack@google.com    bool
39912872Sgabeblack@google.com    operator <= (const ConstDirectIterator &other) const
40012872Sgabeblack@google.com    {
40112872Sgabeblack@google.com        return it_ <= other.it_;
40212872Sgabeblack@google.com    }
40312872Sgabeblack@google.com    bool
40412872Sgabeblack@google.com    operator >= (const ConstDirectIterator &other) const
40512872Sgabeblack@google.com    {
40612872Sgabeblack@google.com        return it_ >= other.it_;
40712872Sgabeblack@google.com    }
40812872Sgabeblack@google.com    bool
40912872Sgabeblack@google.com    operator < (const ConstDirectIterator &other) const
41012872Sgabeblack@google.com    {
41112872Sgabeblack@google.com        return it_ < other.it_;
41212872Sgabeblack@google.com    }
41312872Sgabeblack@google.com    bool
41412872Sgabeblack@google.com    operator > (const ConstDirectIterator &other) const
41512872Sgabeblack@google.com    {
41612872Sgabeblack@google.com        return it_ > other.it_;
41712872Sgabeblack@google.com    }
41812872Sgabeblack@google.com
41912872Sgabeblack@google.com    reference
42012872Sgabeblack@google.com    operator * () const
42112872Sgabeblack@google.com    {
42212872Sgabeblack@google.com        return *Policy::get(static_cast<ElementType *>((void *)*it_));
42312872Sgabeblack@google.com    }
42412872Sgabeblack@google.com    pointer
42512872Sgabeblack@google.com    operator -> () const
42612872Sgabeblack@google.com    {
42712872Sgabeblack@google.com        return Policy::get(static_cast<ElementType *>((void *)*it_));
42812872Sgabeblack@google.com    }
42912872Sgabeblack@google.com    reference
43012872Sgabeblack@google.com    operator [] (difference_type n) const
43112872Sgabeblack@google.com    {
43212872Sgabeblack@google.com        return *Policy::get(static_cast<ElementType *>((void *)it_[n]));
43312872Sgabeblack@google.com    }
43412872Sgabeblack@google.com
43512872Sgabeblack@google.com    difference_type
43612872Sgabeblack@google.com    operator - (ConstDirectIterator const &other) const
43712872Sgabeblack@google.com    {
43812872Sgabeblack@google.com        return it_ - other.it_;
43912872Sgabeblack@google.com    }
44012852Sgabeblack@google.com};
44112852Sgabeblack@google.com
44212852Sgabeblack@google.comtemplate <typename T>
44312852Sgabeblack@google.comclass sc_vector : public sc_vector_base
44412852Sgabeblack@google.com{
44512852Sgabeblack@google.com  public:
44612852Sgabeblack@google.com    using sc_vector_base::size_type;
44712852Sgabeblack@google.com    typedef sc_vector_iter<T> iterator;
44812852Sgabeblack@google.com    typedef sc_vector_iter<const T> const_iterator;
44912852Sgabeblack@google.com
45013271Sgabeblack@google.com    sc_vector() : sc_vector_base(::sc_core::sc_gen_unique_name("vector")) {}
45113271Sgabeblack@google.com    explicit sc_vector(const char *_name) : sc_vector_base(_name) {}
45213271Sgabeblack@google.com    sc_vector(const char *_name, size_type _size) : sc_vector_base(_name)
45312852Sgabeblack@google.com    {
45413271Sgabeblack@google.com        init(_size);
45512852Sgabeblack@google.com    }
45612852Sgabeblack@google.com    template <typename Creator>
45713271Sgabeblack@google.com    sc_vector(const char *_name, size_type _size, Creator creator) :
45813271Sgabeblack@google.com        sc_vector_base(_name)
45912852Sgabeblack@google.com    {
46013271Sgabeblack@google.com        init(_size, creator);
46112852Sgabeblack@google.com    }
46213271Sgabeblack@google.com    virtual ~sc_vector() { clear(); }
46312852Sgabeblack@google.com
46412852Sgabeblack@google.com    void
46513271Sgabeblack@google.com    init(size_type _size)
46612852Sgabeblack@google.com    {
46713271Sgabeblack@google.com        init(_size, &sc_vector<T>::create_element);
46812852Sgabeblack@google.com    }
46912852Sgabeblack@google.com    static T *
47013271Sgabeblack@google.com    create_element(const char *_name, size_type index)
47112852Sgabeblack@google.com    {
47213271Sgabeblack@google.com        return new T(_name);
47312852Sgabeblack@google.com    }
47412852Sgabeblack@google.com
47512852Sgabeblack@google.com    template <typename Creator>
47612852Sgabeblack@google.com    void
47713271Sgabeblack@google.com    init(size_type _size, Creator creator)
47812852Sgabeblack@google.com    {
47913271Sgabeblack@google.com        forceParent();
48013271Sgabeblack@google.com        try {
48113271Sgabeblack@google.com            for (size_type i = 0; i < _size; i++) {
48213271Sgabeblack@google.com                // XXX The name and scope of these objects needs to be handled
48313271Sgabeblack@google.com                // specially.
48413271Sgabeblack@google.com                T *p = creator(sc_gen_unique_name(basename()), i);
48513271Sgabeblack@google.com                objs.push_back(p);
48613271Sgabeblack@google.com            }
48713271Sgabeblack@google.com        } catch (...) {
48813271Sgabeblack@google.com            unforceParent();
48913271Sgabeblack@google.com            clear();
49013271Sgabeblack@google.com            throw;
49113271Sgabeblack@google.com        }
49213271Sgabeblack@google.com        unforceParent();
49313271Sgabeblack@google.com    }
49413271Sgabeblack@google.com
49513271Sgabeblack@google.com    T &operator [] (size_type index) { return *static_cast<T *>(objs[index]); }
49613271Sgabeblack@google.com    const T &
49713271Sgabeblack@google.com    operator [] (size_type index) const
49813271Sgabeblack@google.com    {
49913271Sgabeblack@google.com        return *static_cast<const T *>(objs[index]);
50012852Sgabeblack@google.com    }
50112852Sgabeblack@google.com
50212852Sgabeblack@google.com    T &
50313271Sgabeblack@google.com    at(size_type index)
50412852Sgabeblack@google.com    {
50513271Sgabeblack@google.com        this->checkIndex(index);
50613271Sgabeblack@google.com        return *static_cast<T *>(objs[index]);
50712852Sgabeblack@google.com    }
50812852Sgabeblack@google.com    const T &
50913271Sgabeblack@google.com    at(size_type index) const
51012852Sgabeblack@google.com    {
51113271Sgabeblack@google.com        this->checkIndex(index);
51213271Sgabeblack@google.com        return *static_cast<const T *>(objs[index]);
51312852Sgabeblack@google.com    }
51412852Sgabeblack@google.com
51513271Sgabeblack@google.com    iterator begin() { return objs.begin(); }
51613271Sgabeblack@google.com    iterator end() { return objs.end(); }
51713271Sgabeblack@google.com    const_iterator begin() const { return objs.begin(); }
51813271Sgabeblack@google.com    const_iterator end() const { return objs.end(); }
51913271Sgabeblack@google.com    const_iterator cbegin() const { return objs.begin(); }
52013271Sgabeblack@google.com    const_iterator cend() const { return objs.end(); }
52112852Sgabeblack@google.com
52212852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
52312852Sgabeblack@google.com    iterator
52413271Sgabeblack@google.com    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
52512852Sgabeblack@google.com    {
52613271Sgabeblack@google.com        return bind(c.begin(), c.end());
52712852Sgabeblack@google.com    }
52812852Sgabeblack@google.com
52912852Sgabeblack@google.com    template <typename BindableContainer>
53012852Sgabeblack@google.com    iterator
53113271Sgabeblack@google.com    bind(BindableContainer &c)
53212852Sgabeblack@google.com    {
53313271Sgabeblack@google.com        return bind(c.begin(), c.end());
53412852Sgabeblack@google.com    }
53512852Sgabeblack@google.com
53612852Sgabeblack@google.com    template <typename BindableIterator>
53712852Sgabeblack@google.com    iterator
53813271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last)
53912852Sgabeblack@google.com    {
54013271Sgabeblack@google.com        return bind(first, last, this->begin());
54112852Sgabeblack@google.com    }
54212852Sgabeblack@google.com
54312852Sgabeblack@google.com    template <typename BindableIterator>
54412852Sgabeblack@google.com    iterator
54513271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last, iterator from)
54612852Sgabeblack@google.com    {
54713271Sgabeblack@google.com        if (!size() || from == end() || first == last)
54813271Sgabeblack@google.com            reportEmpty(kind(), from == end());
54913271Sgabeblack@google.com
55013271Sgabeblack@google.com        while (from != end() && first != last)
55113271Sgabeblack@google.com            (*from++).bind(*first++);
55213271Sgabeblack@google.com        return from;
55312852Sgabeblack@google.com    }
55412852Sgabeblack@google.com
55512852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
55612852Sgabeblack@google.com    iterator
55712852Sgabeblack@google.com    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
55812852Sgabeblack@google.com    {
55913271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
56012852Sgabeblack@google.com    }
56112852Sgabeblack@google.com
56212852Sgabeblack@google.com    template <typename ArgumentContainer>
56312852Sgabeblack@google.com    iterator
56413271Sgabeblack@google.com    operator () (ArgumentContainer &c)
56512852Sgabeblack@google.com    {
56613271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
56712852Sgabeblack@google.com    }
56812852Sgabeblack@google.com
56912852Sgabeblack@google.com    template <typename ArgumentIterator>
57012852Sgabeblack@google.com    iterator
57113271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last)
57212852Sgabeblack@google.com    {
57313271Sgabeblack@google.com        return (*this)(first, last, this->begin());
57412852Sgabeblack@google.com    }
57512852Sgabeblack@google.com
57612852Sgabeblack@google.com    template <typename ArgumentIterator>
57712852Sgabeblack@google.com    iterator
57813271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
57912852Sgabeblack@google.com    {
58013271Sgabeblack@google.com        if (!size() || from == end() || first == last)
58113271Sgabeblack@google.com            reportEmpty(kind(), from == end());
58213271Sgabeblack@google.com
58313271Sgabeblack@google.com        while (from != end() && first != last)
58413271Sgabeblack@google.com            (*from++)(*first++);
58513271Sgabeblack@google.com        return from;
58612852Sgabeblack@google.com    }
58712852Sgabeblack@google.com
58812852Sgabeblack@google.com  private:
58912852Sgabeblack@google.com    // Disabled
59012852Sgabeblack@google.com    sc_vector(const sc_vector &) : sc_vector_base() {}
59112852Sgabeblack@google.com    sc_vector &operator = (const sc_vector &) { return *this; }
59213271Sgabeblack@google.com
59313271Sgabeblack@google.com    void
59413271Sgabeblack@google.com    clear()
59513271Sgabeblack@google.com    {
59613271Sgabeblack@google.com        for (auto obj: objs)
59713271Sgabeblack@google.com            delete static_cast<T *>(obj);
59813271Sgabeblack@google.com    }
59913271Sgabeblack@google.com
60013271Sgabeblack@google.com    template <typename, typename>
60113271Sgabeblack@google.com    friend class sc_vector_assembly;
60213271Sgabeblack@google.com
60313271Sgabeblack@google.com    sc_object *
60413271Sgabeblack@google.com    objectCast(void *ptr) const
60513271Sgabeblack@google.com    {
60613271Sgabeblack@google.com        return implicitCast(static_cast<T *>(ptr));
60713271Sgabeblack@google.com    }
60812852Sgabeblack@google.com};
60912852Sgabeblack@google.com
61012852Sgabeblack@google.comtemplate <typename T, typename MT>
61112852Sgabeblack@google.comclass sc_vector_assembly
61212852Sgabeblack@google.com{
61312852Sgabeblack@google.com  public:
61412852Sgabeblack@google.com    friend sc_vector_assembly<T, MT> sc_assemble_vector<>(
61512872Sgabeblack@google.com            sc_vector<T> &, MT (T::*));
61612852Sgabeblack@google.com
61712852Sgabeblack@google.com    typedef size_t size_type;
61812872Sgabeblack@google.com    typedef sc_vector_iter<T, sc_member_access<T, MT> > iterator;
61912872Sgabeblack@google.com    typedef sc_vector_iter<
62012872Sgabeblack@google.com        const T, sc_member_access<const T, const MT> > const_iterator;
62112872Sgabeblack@google.com    typedef MT (T::*MemberType);
62212852Sgabeblack@google.com
62313271Sgabeblack@google.com    sc_vector_assembly(const sc_vector_assembly &other) :
62413271Sgabeblack@google.com        vec_(other.vec_), ptr_(other.ptr_)
62513271Sgabeblack@google.com    {}
62612852Sgabeblack@google.com
62712872Sgabeblack@google.com    iterator begin() { return iterator(vec_->begin().it_, ptr_); }
62812872Sgabeblack@google.com    iterator end() { return iterator(vec_->end().it_, ptr_); }
62912852Sgabeblack@google.com
63012852Sgabeblack@google.com    const_iterator
63112852Sgabeblack@google.com    cbegin() const
63212852Sgabeblack@google.com    {
63312872Sgabeblack@google.com        return const_iterator(vec_->begin().it_, ptr_);
63412852Sgabeblack@google.com    }
63512852Sgabeblack@google.com    const_iterator
63612852Sgabeblack@google.com    cend() const
63712852Sgabeblack@google.com    {
63812872Sgabeblack@google.com        return const_iterator(vec_->end().it_, ptr_);
63912852Sgabeblack@google.com    }
64012852Sgabeblack@google.com
64112872Sgabeblack@google.com    const_iterator
64212872Sgabeblack@google.com    begin() const
64312852Sgabeblack@google.com    {
64412872Sgabeblack@google.com        return const_iterator(vec_->begin().it_, ptr_);
64512852Sgabeblack@google.com    }
64612872Sgabeblack@google.com    const_iterator
64712872Sgabeblack@google.com    end() const
64812872Sgabeblack@google.com    {
64912872Sgabeblack@google.com        return const_iterator(vec_->end().it_, ptr_);
65012872Sgabeblack@google.com    }
65112872Sgabeblack@google.com
65212872Sgabeblack@google.com    size_type size() const { return vec_->size(); }
65312872Sgabeblack@google.com
65412852Sgabeblack@google.com    std::vector<sc_object *>
65512852Sgabeblack@google.com    get_elements() const
65612852Sgabeblack@google.com    {
65713271Sgabeblack@google.com        std::vector<sc_object *> ret;
65813271Sgabeblack@google.com        for (const_iterator it = begin(); it != end(); it++) {
65913271Sgabeblack@google.com            sc_object *obj_ptr = vec_->objectCast(const_cast<MT *>(&*it));
66013271Sgabeblack@google.com
66113271Sgabeblack@google.com            if (obj_ptr)
66213271Sgabeblack@google.com                ret.push_back(obj_ptr);
66313271Sgabeblack@google.com        }
66413271Sgabeblack@google.com        return ret;
66512852Sgabeblack@google.com    }
66612852Sgabeblack@google.com
66712852Sgabeblack@google.com    typename iterator::reference
66812872Sgabeblack@google.com    operator [] (size_type i)
66912852Sgabeblack@google.com    {
67012872Sgabeblack@google.com        return (*vec_)[i].*ptr_;
67112852Sgabeblack@google.com    }
67212852Sgabeblack@google.com    typename const_iterator::reference
67312872Sgabeblack@google.com    operator [] (size_type i) const
67412852Sgabeblack@google.com    {
67512872Sgabeblack@google.com        return (*vec_)[i].*ptr_;
67612852Sgabeblack@google.com    }
67712852Sgabeblack@google.com
67812852Sgabeblack@google.com    typename iterator::reference
67912872Sgabeblack@google.com    at(size_type i)
68012852Sgabeblack@google.com    {
68112872Sgabeblack@google.com        return vec_->at(i).*ptr_;
68212852Sgabeblack@google.com    }
68312852Sgabeblack@google.com    typename const_iterator::reference
68412872Sgabeblack@google.com    at(size_type i) const
68512852Sgabeblack@google.com    {
68612872Sgabeblack@google.com        return vec_->at(i).*ptr_;
68712852Sgabeblack@google.com    }
68812852Sgabeblack@google.com
68912852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
69012852Sgabeblack@google.com    iterator
69113271Sgabeblack@google.com    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
69212852Sgabeblack@google.com    {
69313271Sgabeblack@google.com        return bind(c.begin(), c.end());
69412852Sgabeblack@google.com    }
69512852Sgabeblack@google.com
69612852Sgabeblack@google.com    template <typename BindableContainer>
69712852Sgabeblack@google.com    iterator
69813271Sgabeblack@google.com    bind(BindableContainer &c)
69912852Sgabeblack@google.com    {
70013271Sgabeblack@google.com        return bind(c.begin(), c.end());
70112852Sgabeblack@google.com    }
70212852Sgabeblack@google.com
70312852Sgabeblack@google.com    template <typename BindableIterator>
70412852Sgabeblack@google.com    iterator
70513271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last)
70612852Sgabeblack@google.com    {
70713271Sgabeblack@google.com        return bind(first, last, this->begin());
70812852Sgabeblack@google.com    }
70912852Sgabeblack@google.com
71012852Sgabeblack@google.com    template <typename BindableIterator>
71112852Sgabeblack@google.com    iterator
71213271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last, iterator from)
71312852Sgabeblack@google.com    {
71413271Sgabeblack@google.com        if (!size() || from == end() || first == last)
71513271Sgabeblack@google.com            vec_->reportEmpty("sc_vector_assembly", from == end());
71613271Sgabeblack@google.com
71713271Sgabeblack@google.com        while (from != end() && first != last)
71813271Sgabeblack@google.com            (*from++).bind(*first++);
71913271Sgabeblack@google.com        return from;
72012852Sgabeblack@google.com    }
72112852Sgabeblack@google.com
72212852Sgabeblack@google.com    template <typename BindableIterator>
72312852Sgabeblack@google.com    iterator
72413271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last,
72513271Sgabeblack@google.com            typename sc_vector<T>::iterator from)
72612852Sgabeblack@google.com    {
72713271Sgabeblack@google.com        return bind(first, last, iterator(from.it_, ptr_));
72812852Sgabeblack@google.com    }
72912852Sgabeblack@google.com
73012852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
73112852Sgabeblack@google.com    iterator
73213271Sgabeblack@google.com    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
73312852Sgabeblack@google.com    {
73413271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
73512852Sgabeblack@google.com    }
73612852Sgabeblack@google.com
73712852Sgabeblack@google.com    template <typename ArgumentContainer>
73812852Sgabeblack@google.com    iterator
73913271Sgabeblack@google.com    operator () (ArgumentContainer &c)
74012852Sgabeblack@google.com    {
74113271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
74212852Sgabeblack@google.com    }
74312852Sgabeblack@google.com
74412852Sgabeblack@google.com    template <typename ArgumentIterator>
74512852Sgabeblack@google.com    iterator
74613271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last)
74712852Sgabeblack@google.com    {
74813271Sgabeblack@google.com        return (*this)(first, last, this->begin());
74912852Sgabeblack@google.com    }
75012852Sgabeblack@google.com
75112852Sgabeblack@google.com    template <typename ArgumentIterator>
75212852Sgabeblack@google.com    iterator
75313271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
75412852Sgabeblack@google.com    {
75513271Sgabeblack@google.com        if (!size() || from == end() || first == last)
75613271Sgabeblack@google.com            vec_->reportEmpty("sc_vector_assembly", from == end());
75713271Sgabeblack@google.com
75813271Sgabeblack@google.com        while (from != end() && first != last)
75913271Sgabeblack@google.com            (*from++)(*first++);
76013271Sgabeblack@google.com        return from;
76112852Sgabeblack@google.com    }
76212852Sgabeblack@google.com
76312852Sgabeblack@google.com    template <typename ArgumentIterator>
76412852Sgabeblack@google.com    iterator
76513271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last,
76613271Sgabeblack@google.com                 typename sc_vector<T>::iterator from)
76712852Sgabeblack@google.com    {
76813271Sgabeblack@google.com        return (*this)(first, last, iterator(from.it_, ptr_));
76912852Sgabeblack@google.com    }
77012852Sgabeblack@google.com
77112852Sgabeblack@google.com  private:
77212872Sgabeblack@google.com    sc_vector_assembly(sc_vector<T> &v, MemberType ptr) :
77312872Sgabeblack@google.com        vec_(&v), ptr_(ptr)
77412872Sgabeblack@google.com    {}
77512872Sgabeblack@google.com
77612872Sgabeblack@google.com    sc_vector<T> *vec_;
77712872Sgabeblack@google.com    MemberType ptr_;
77812852Sgabeblack@google.com};
77912852Sgabeblack@google.com
78012852Sgabeblack@google.comtemplate <typename T, typename MT>
78112852Sgabeblack@google.comsc_vector_assembly<T, MT>
78212872Sgabeblack@google.comsc_assemble_vector(sc_vector<T> &v, MT (T::*ptr))
78312852Sgabeblack@google.com{
78412872Sgabeblack@google.com    return sc_vector_assembly<T, MT>(v, ptr);
78512852Sgabeblack@google.com}
78612852Sgabeblack@google.com
78712852Sgabeblack@google.com} // namespace sc_core
78812852Sgabeblack@google.com
78912852Sgabeblack@google.com#endif  //__SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
790