🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.g++.help
Article #840

safestl with g++

#840
From: Kate Hedstrom
Date: Mon, 27 Nov 1995 15:10
838 lines
22604 bytes
I tried to get Cay Horstmann's safestl working with g++.  Most of it
works and is available in:

   ftp://imcs.rutgers.edu/pub/kate/safestl.tar.gz

I do not have the vectors working and the compiler error is:

/usr/local/lib/g++-include/algobase.h: In function `void distance(class
vector<char>::const_iterator, class vector<char>::const_iterator, long
unsigned int &)':
/usr/local/lib/g++-include/algobase.h:87: type unification failed for
function template `template <class T, class Distance> struct
input_iterator_tag iterator_category(input_iterator<...> &)'

Does anyone know how to work around this?  An example program is
below.  This is with g++/libg++ 2.7.1 on a Sun Sparc under SunOS
4.1.3 and SunOS 5.4, as well as on a Sun-3.

Kate

/*
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 */

/*
The Safe STL enhancements are

Copyright (C) Horstmann Software Design Corp. 1995. All Rights Reserved.

You may freely use, copy, modify, or distribute these Safe STL enhancements
and this documentation for any purpose, provided (1) you charge NO FEE for
distributing these copyrighted materials and (2) you include both the
copyright notice and permission notice from Hewlett-Packard Company and this
copyright notice and permission notice. Horstmann Software Design Corporation
specifically disclaims that these materials might do anything useful at all.
If they work for you and don't destroy anything, you are in luck.
There is no free technical support available for these materials.

I marked all modifications to the STL source with CSH (Cay S. Horstmann)

Please send bug reports/suggestions to horstman@cs.sjsu.edu.
For the most current version of these files, see
http://www.mathcs.sjsu.edu/faculty/horstman/safestl.html
*/

// I put the g++ ifdefs in and got it more or less working.
// Kate Hedstrom (kate@imcs.rutgers.edu)

#ifndef VECTOR_H
#define VECTOR_H

#include <function.h>
#include <algobase.h>
#ifndef __GNUG__
#include <bool.h>
#endif
#include <iterator.h> // CSH
// CSH begin
#ifndef assert
#include <assert.h>
#endif
// CSH end

#ifndef Allocator
#define Allocator allocator
#include <defalloc.h>
#endif

#ifndef vector
#define vector vector
#endif

template <class T>
class vector {
public:
    
    typedef Allocator<T> vector_allocator;
    typedef T value_type;
    typedef vector_allocator::pointer pointer;
// CSH    typedef vector_allocator::pointer iterator;
// CSH    typedef vector_allocator::const_pointer const_iterator;
    typedef vector_allocator::reference reference;
    typedef vector_allocator::const_reference const_reference;
    typedef vector_allocator::size_type size_type;
    typedef vector_allocator::difference_type difference_type;

	// CSH begin

    class iterator;
    class const_iterator;

    class iterator_base
    {
    private:
	friend class iterator;
	friend class const_iterator;
	friend class vector<T>;

	iterator_base* _next_iter;
	vector<T>* _owner;
	pointer _pos;

	iterator_base() : _owner(0) {}
	bool valid(difference_type n = 0) const
	{
	    return _owner != 0 && _pos + n >= _owner->start && !past_end(n);
	}
	bool past_end(difference_type n = 0) const
	{
	    return _owner != 0 && _pos + n >= _owner->finish;
	}
	bool orphan() const
	{
	    return _owner == 0;
	}
	bool same_owner(const iterator_base& b) const
	{
	    if (orphan() || b.orphan()) return false;
	    return _owner == b._owner;
	}
	void attach(pointer n, vector<T>* owner)
	{
	    _pos = n;  _owner = owner;
	    // add into iterator chain of owner
	    _next_iter = _owner->_iter_chain;
	    _owner->_iter_chain = this;
	}

	void detach()
	{  // remove from iterator chain of owner
	    if (_owner)
	    {
		iterator_base* p = _owner->_iter_chain;
		iterator_base* ppre = 0;
		while (p != 0 && p != this)
		{
		    ppre = p;
		    p = p->_next_iter;
		}
		if (ppre != 0)
		    ppre->_next_iter = p->_next_iter;
		else
		    _owner->_iter_chain = p->_next_iter;
		 _owner = 0;
	    }
	}

    };
    friend class iterator_base;
	// CSH end

	// CSH begin

    class iterator : public
	 random_access_iterator<T, difference_type>,
				 private iterator_base
    {
    private:
	friend class vector<T>;
	iterator(pointer x, vector<T>* owner)
	{
	    attach(x, owner);
	}
    public:
	iterator() {}

	iterator(const iterator& b)
	{
	    attach(b._pos, b._owner);
	}

	iterator& operator=(const iterator& b)
	{
	    detach();
	    attach(b._pos, b._owner);
	    return *this;
	}

	~iterator()
	{
	    detach();
	}

	reference operator*()
	{
	    assert(valid());
	    return *_pos;
	}
	reference operator[](difference_type n)
	{
	    assert(valid(n));
	    return _pos[n];
	}
	iterator& operator+=(difference_type n)
	{
	    assert(valid(n) || past_end(n));
	    _pos += n;
	    return *this;
	}
	iterator& operator-=(difference_type n)
	{
	    assert(valid(-n));
	    _pos -= n;
	    return *this;
	}
	iterator& operator++()
	{
	    assert(valid(1) || past_end(1));
	    _pos++;
	    return *this;
	}
	iterator operator++(int)
	{
	    iterator temp = *this;
	    assert(valid(1) || past_end(1));
	    _pos++;
	    return temp;
	}
	iterator& operator--()
	{
	    assert(valid(-1));
	    _pos--;
	    return *this;
	}
	iterator operator--(int)
	{
	    iterator temp = *this;
	    assert(valid(-1));
	    _pos--;
	    return temp;
	}
	iterator operator+(difference_type n) const
	{
	    iterator temp = *this;
	    temp += n;
	    return temp;
	}
	iterator operator-(difference_type n) const
	{
	    iterator temp = *this;
	    temp -= n;
	    return temp;
	}
	bool operator==(const iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos == b._pos;
	}
	bool operator<=(const iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos <= b._pos;
	}
	bool operator>=(const iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos >= b._pos;
	}
	bool operator!=(const iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos != b._pos;
	}
	bool operator<(const iterator& b)  const
	{
	    assert(same_owner(b));
	    return _pos < b._pos;
	}
	bool operator>(const iterator& b)  const
	{
	    assert(same_owner(b));
	    return _pos > b._pos;
	}
	difference_type operator-(const iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos - b._pos;
	}

	friend class const_iterator;
    };

	// CSH end

	// CSH begin

    class const_iterator : public
	random_access_iterator<T, difference_type>,
				 private iterator_base
    {
    private:
	friend class vector<T>;
	const_iterator(pointer x, const vector<T>* owner)
	{
	    attach(x, (/*non-const*/vector<T>*) owner);
	}
    public:
	const_iterator() {}

	const_iterator(const const_iterator& b)
	{
	    attach(b._pos, b._owner);
	}

	const_iterator& operator=(const const_iterator& b)
	{
	    detach();
	    attach(b._pos, b._owner);
	    return *this;
	}

	~const_iterator()
	{
	    detach();
	}

	const_iterator(const iterator& b)
	{
	    attach(b._pos, b._owner);
	}

	const_iterator& operator=(const iterator& b)
	{
	    detach();
	    attach(b._pos, b._owner);
	    return *this;
	}

	const_reference operator*()
	{
	    assert(valid());
	    return *_pos;
	}
	const_reference operator[](difference_type n)
	{
	    assert(valid(n));
	    return _pos[n];
	}
	const_iterator& operator+=(difference_type n)
	{
	    assert(valid(n) || past_end(n));
	    _pos += n;
	    return *this;
	}
	const_iterator& operator-=(difference_type n)
	{
	    assert(valid(-n));
	    _pos -= n;
	    return *this;
	}
	const_iterator& operator++()
	{
	    assert(valid(1) || past_end(1));
	    _pos++;
	    return *this;
	}
	const_iterator operator++(int)
	{
	    const_iterator temp = *this;
	    assert(valid(1) || past_end(1));
	    _pos++;
	    return temp;
	}
	const_iterator& operator--()
	{
	    assert(valid(-1));
	    _pos--;
	    return *this;
	}
	const_iterator operator--(int)
	{
	    const_iterator temp = *this;
	    assert(valid(-1));
	    _pos--;
	    return temp;
	}
	const_iterator operator+(difference_type n) const
	{
	    const_iterator temp = *this;
	    temp += n;
	    return temp;
	}
	const_iterator operator-(difference_type n) const
	{
	    const_iterator temp = *this;
	    temp -= n;
	    return temp;
	}
	bool operator==(const const_iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos == b._pos;
	}
	bool operator<=(const const_iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos <= b._pos;
	}
	bool operator>=(const const_iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos >= b._pos;
	}
	bool operator!=(const const_iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos != b._pos;
	}
	bool operator<(const const_iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos < b._pos;
	}
	bool operator>(const const_iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos > b._pos;
	}
	difference_type operator-(const const_iterator& b) const
	{
	    assert(same_owner(b));
	    return _pos - b._pos;
	}

    };

	// CSH end

    typedef reverse_iterator<const_iterator, value_type, const_reference, 
                             difference_type>  const_reverse_iterator;
    typedef reverse_iterator<iterator, value_type, reference, difference_type>
        reverse_iterator;


protected:
    static Allocator<T> static_allocator;
	/* iterator CSH */ pointer start;
	/* iterator CSH */ pointer finish;
	/* iterator CSH */ pointer end_of_storage;
#ifdef __GNUG__
    void insert_aux(iterator position, const T& x) {
	insert_aux(vector_iterator<T>(position), x);
    }
    void insert_aux(vector_iterator<T> position, const T& x);
#else
    void insert_aux(iterator position, const T& x);
#endif

    iterator_base* _iter_chain; // CSH

		// CSH begin

    void orphan_iterators()
    {
	iterator_base* p = _iter_chain;
	_iter_chain = 0;
	while (p != 0)
	{
	    p->_owner = 0;
	    p->_pos = 0;
	    iterator_base* pnext = p->_next_iter;
	    p->_next_iter = 0;
	    p = pnext;
	}
    }

    void orphan_iterators_after(pointer pos)
    {
	iterator_base* p = _iter_chain;
	iterator_base* pprev = 0;
	while (p != 0)
	{
	    iterator_base* pnext = p->_next_iter;
	    if (p->_pos > pos)
	    {  p->_owner = 0;
		p->_pos = 0;
		p->_next_iter = 0;
		if (pprev) pprev->_next_iter = pnext;
		else _iter_chain = pnext;
	    }
	    else
		pprev = p;
	    p = pnext;
	}
    }

    bool owns(iterator_base p)
    {
	return p._owner == this;
    }

		// CSH end


public:
    iterator begin() { return iterator(start, this); /* CSH */ }
    const_iterator begin() const { return const_iterator(start, this); /* CSH */}
    iterator end() { return iterator(finish, this); /* CSH */}
    const_iterator end() const { return const_iterator(finish, this); /* CSH */}
    reverse_iterator rbegin() { return reverse_iterator(end()); }
    const_reverse_iterator rbegin() const { 
        return const_reverse_iterator(end()); 
    }
    reverse_iterator rend() { return reverse_iterator(begin()); }
    const_reverse_iterator rend() const { 
        return const_reverse_iterator(begin()); 
    }
    size_type size() const { return size_type(end() - begin()); }
    size_type max_size() const { return static_allocator.max_size(); }
    size_type capacity() const { return size_type(end_of_storage - /* begin() CSH */ start); }
    bool empty() const { return begin() == end(); }
    reference operator[](size_type n) { return *(begin() + n); }
    const_reference operator[](size_type n) const { return *(begin() + n); }
    vector() : start(0), finish(0), end_of_storage(0), _iter_chain(0) /* CSH */ {}
    vector(size_type n, const T& value = T()) : _iter_chain(0) /* CSH */ {
	start = static_allocator.allocate(n);
	uninitialized_fill_n(start, n, value);
	finish = start + n;
	end_of_storage = finish;
    }
    vector(const vector<T>& x) : _iter_chain(0) /* CSH */ {
	start = static_allocator.allocate(x.end() - x.begin());
	finish = uninitialized_copy(x.begin(), x.end(), start);
	end_of_storage = finish;
    }
    vector(const_iterator first, const_iterator last) : _iter_chain(0) /* CSH */ {
	assert(first.same_owner(last)); // CSH
	size_type n = 0;
	distance(first, last, n);
	start = static_allocator.allocate(n);
	finish = uninitialized_copy(first, last, start);
	end_of_storage = finish;
    }
    ~vector() { 
	orphan_iterators(); // CSH
	destroy(start, finish);
	static_allocator.deallocate(start);
    }
    vector<T>& operator=(const vector<T>& x);
    void reserve(size_type n) {
	if (capacity() < n) {
	    /* iterator CSH */ pointer tmp = static_allocator.allocate(n);
	    uninitialized_copy(begin(), end(), tmp);
	    orphan_iterators(); // CSH
	    destroy(start, finish);
	    static_allocator.deallocate(start);
	    finish = tmp + size();
	    start = tmp;
	    end_of_storage = /* begin() CSH */ start + n;
	}
    }
    reference front() { return *begin(); }
    const_reference front() const { return *begin(); }
    reference back() { return *(end() - 1); }
    const_reference back() const { return *(end() - 1); }
    void push_back(const T& x) {
	if (finish != end_of_storage) {
	    /* Borland bug */
	    construct(finish, x);
	    finish++;
	} else
	    insert_aux(end(), x);
    }
    void swap(vector<T>& x) {
	orphan_iterators(); // CSH
	x.orphan_iterators(); // CSH
	::swap(start, x.start);
	::swap(finish, x.finish);
	::swap(end_of_storage, x.end_of_storage);
    }
    iterator insert(iterator position, const T& x) {
	assert(owns(position)); // CSH
	size_type n = position - begin();
	if (finish != end_of_storage && position == end()) {
	    /* Borland bug */
	    construct(finish, x);
	    finish++;
	} else
	    insert_aux(position, x);
	return begin() + n;
    }
#ifdef __GNUG__
    void insert (iterator position, const_iterator first, 
		 const_iterator last) {
        insert(vector_iterator<T>(position),
	       vector_const_iterator<T>(first),
	       vector_const_iterator<T>(last));
    }
    void insert (vector_iterator<T> position, vector_const_iterator<T> first, 
		 vector_const_iterator<T> last);
    void insert (iterator position, size_type n, const T& x) {
	insert(vector_iterator<T>(position), n, x);
    }
    void insert (vector_iterator<T> position, size_type n, const T& x);
#else
    void insert (iterator position, const_iterator first, 
		 const_iterator last);
    void insert (iterator position, size_type n, const T& x);
#endif
    void pop_back() {
	/* Borland bug */
        --finish;
	orphan_iterators_after(finish); // CSH
        destroy(finish);
    }
    void erase(iterator position) {
	assert(owns(position)); // CSH
	if (position + 1 != end())
	    copy(position + 1, end(), position);
	/* Borland bug */
	--finish;
	orphan_iterators_after(finish); // CSH
	destroy(finish);
    }
    void erase(iterator first, iterator last) {
	assert(owns(first) && owns(last)); // CSH
	vector<T>::iterator i = copy(last, end(), first);
	destroy(i, /* finish CSH */ end());
	// work around for destroy(copy(last, end(), first), finish);
	finish = finish - (last - first); 
	orphan_iterators_after(finish); // CSH
    }
};

#ifdef __GNUG__
template <class T>
struct vector_iterator {
    vector<T>::iterator it;
    vector_iterator(vector<T>::iterator i) : it(i) {}
    operator vector<T>::iterator() {
	return it;
    }
};

template <class T>
inline T* value_type(const vector_iterator<T>&) {
    return (T*)(0);
}


template <class T>
struct vector_const_iterator {
    vector<T>::const_iterator it;
    vector_const_iterator(vector<T>::const_iterator i) : it(i) {}
    operator vector<T>::const_iterator() {
	return it;
    }
};
#endif

template <class T>
inline bool operator==(const vector<T>& x, const vector<T>& y) {
    return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
}

template <class T>
inline bool operator<(const vector<T>& x, const vector<T>& y) {
    return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}

#ifndef __GNUG__
template <class T>
vector<T>::vector_allocator vector<T>::static_allocator;
#endif

template <class T>
vector<T>& vector<T>::operator=(const vector<T>& x) {
    if (&x == this) return *this;
    orphan_iterators(); // CSH
    if (x.size() > capacity()) {
	destroy(start, finish);
	static_allocator.deallocate(start);
	start = static_allocator.allocate(x.end() - x.begin());
	end_of_storage = uninitialized_copy(x.begin(), x.end(), start);
    } else if (size() >= x.size()) {
	vector<T>::iterator i = copy(x.begin(), x.end(), begin());
	destroy(i, /* finish CSH */ end());
	// work around for destroy(copy(x.begin(), x.end(), begin()), finish);
    } else {
	copy(x.begin(), x.begin() + size(), begin());
	uninitialized_copy(x.begin() + size(), x.end(), /* begin() CSH */ start+ size());
    }
    finish = /* begin() CSH */ start + x.size();
    return *this;
}

template <class T>
#ifdef __GNUG__
void vector<T>::insert_aux(vector_iterator<T> posn, const T& x) {
    iterator position = posn;
#else
void vector<T>::insert_aux(iterator position, const T& x) {
#endif
    if (finish != end_of_storage) {
	construct(finish, *(finish - 1));
	copy_backward(position, /* finish CSH */ end() - 1, finish);
	*position = x;
	++finish;
    } else {
	size_type len = size() ? 2 * size() 
	    : static_allocator.init_page_size();
	/* iterator CSH */ pointer tmp = static_allocator.allocate(len);
	uninitialized_copy(begin(), position, tmp);
	construct(tmp + (position - begin()), x);
	uninitialized_copy(position, end(), tmp + (position - begin()) + 1); 
	orphan_iterators(); // CSH
	destroy(begin(), end());
	static_allocator.deallocate(/* begin() CSH */ start);
	end_of_storage = tmp + len;
	finish = tmp + size() + 1;
	start = tmp;
    }
}

template <class T>
#ifdef __GNUG__
void vector<T>::insert(vector_iterator<T> posn,
		       size_t n,
		       const T& x) {
    iterator position = posn;
#else
void vector<T>::insert(iterator position, size_type n, const T& x) {
#endif
    assert(owns(position)); // CSH
    if (n == 0) return;
    if ((size_type) (end_of_storage - finish) >= n) {
	if ((size_type) (end() - position) > n) {
	    uninitialized_copy(end() - n, end(), /* end() CSH */ finish);
	    copy_backward(position, end() - n, end());
	    fill(position, position + n, x);
	} else {
	    uninitialized_copy(position, end(), /* position CSH */ start + (position - begin()) + n);
	    fill(position, end(), x);
	    uninitialized_fill_n(/* end() CSH */ finish, n - (end() - position), x);
	}
	finish += n;
    } else {
	size_type len = size() + max(size(), n);
	/* iterator CSH */ pointer tmp = static_allocator.allocate(len);
	uninitialized_copy(begin(), position, tmp);
	uninitialized_fill_n(tmp + (position - begin()), n, x);
	uninitialized_copy(position, end(), tmp + (position - begin() + n));
	orphan_iterators(); // CSH
	destroy(begin(), end());
	static_allocator.deallocate(/* begin() CSH */ start);
	end_of_storage = tmp + len;
	finish = tmp + size() + n;
	start = tmp;
    }
}

template <class T>
#ifdef __GNUG__
void vector<T>::insert(vector_iterator<T> posn, 
		       vector_const_iterator<T> fi, 
		       vector_const_iterator<T> la) {
    iterator position = posn;
    const_iterator first = fi;
    const_iterator last = la;
#else
void vector<T>::insert(iterator position, 
		       const_iterator first, 
		       const_iterator last) {
#endif
    assert(owns(position)); // CSH
    if (first == last) return;
    size_type n = 0;
    distance(first, last, n);
    if ((size_type) (end_of_storage - finish) >= n) {
	if ((size_type) (end() - position) > n) {
	    uninitialized_copy(end() - n, end(), /* end() CSH */ finish);
	    copy_backward(position, end() - n, end());
	    copy(first, last, position);
	} else {
	    uninitialized_copy(position, end(), /* position CSH */ start + (position - begin()) + n);
	    copy(first, first + (end() - position), position);
	    uninitialized_copy(first + (end() - position), last, /* end() CSH */ finish);
	}
	finish += n;
    } else {
	size_type len = size() + max(size(), n);
	/* iterator CSH */ pointer tmp = static_allocator.allocate(len);
	uninitialized_copy(begin(), position, tmp);
	uninitialized_copy(first, last, tmp + (position - begin()));
	uninitialized_copy(position, end(), tmp + (position - begin() + n));
	orphan_iterators(); // CSH
	destroy(begin(), end());
	static_allocator.deallocate(/* begin() CSH */ start);
	end_of_storage = tmp + len;
	finish = tmp + size() + n;
	start = tmp;
    }
}

#if 0
// CSH can't get this to work with Borland 4.5
// Error: Template function argument 'T' not used in argument types
// so don't use n + p

template<class T>
inline vector<T>::iterator operator+(vector<T>::difference_type n,
      const vector<T>::iterator& p)
{
    return p + n;
}

template<class T>
inline vector<T>::const_iterator operator+(vector<T>::difference_type n,
      const vector<T>::const_iterator& p)
{
    return p + n;
}

#endif

#undef Allocator
#undef vector

#endif

#include <iostream.h>

int main()
{
    vector<char> c;
    return 0;
}
Technical Details
Message-ID: <199511271516.KAA26275@ahab.rutgers.edu>
Path: arc1-ca.pugleaf.net!ahab.rutgers.edu!kate

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!ahab.rutgers.edu!kate
From: kate@ahab.rutgers.edu (Kate Hedstrom)
Newsgroups: gnu.g++.help,comp.lang.c++
Subject: safestl with g++
Date: 27 Nov 1995 10:10:28 -0500
Organization: Gatewayed from the GNU Project mailing list help-g++@prep.ai.mit.edu
Sender: daemon@cis.ohio-state.edu
Distribution: world
Message-ID: <199511271516.KAA26275@ahab.rutgers.edu>