`
qiezi
  • 浏览: 497799 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

仿STL的vector,写了一组array操作方法。

    博客分类:
  • D
阅读更多
文档从MSDN抄过来的,稍稍改了一下。
module array;

struct random_access_iterator(T)
{
private:
	alias random_access_iterator!(T) self_type;
	T[] array;
	size_t pos;

public:
	static self_type opCall(T[] array, size_t pos)
	{
		self_type ret;
		ret.array = array;
		ret.pos   = pos;
		return ret;
	}

	T[] get_array()
	{
		return array;
	}

	size_t get_pos()
	{
		return pos;
	}

	T opCall()
	{
		return array[pos];
	}

	void opAssign(T value)
	{
		array[pos] = value;
	}

	void check_array(T[] array)
	{
		if (array !is this.array)
			throw new Exception("not same array object");
		if (this.pos > array.length)
			throw new Exception("invalid iterator");
	}

	self_type
	opAdd(int delta)
	{
		return self_type(this.array, this.pos + delta);
	}

	self_type
	opAdd_r(int delta)
	{
		return opAdd(delta);
	}

	self_type
	opPostInc()
	{
		return opAddAssign(1);
	}

	self_type
	opAddAssign(int delta)
	{
		this.pos += delta;
		if (this.pos > this.array.length)
			this.pos = this.array.length;
		return *this;
	}

	self_type
	opSub(int delta)
	{
		return self_type(this.array, this.pos - delta);
	}

	self_type
	opSub_r(int delta)
	{
		return opSub(delta);
	}

	self_type
	opPostSub()
	{
		return opSubAssign(1);
	}

	self_type
	opSubAssign(int delta)
	{
		this.pos -= delta;
		if (this.pos > this.array.length)
			this.pos = this.array.length;
		return *this;
	}

	self_type
	opNeg()
	{
		int pos = (-this.pos) % this.array.length;
		return self_type(this.array, pos);
	}

	T opCast()
	{
		return this.array[this.pos];
	}

	int opCmp(self_type rhs)
	{
		if (this.array != rhs.array)
			throw new Exception("can't compare iterators of different array");
		return cast(int)this.pos - cast(int)rhs.pos;
	}

	int opEquals(self_type rhs)
	{
		if (this.array == rhs.array && 
			this.pos == rhs.pos)
			return 1;
		return 0;
	}
}

template iterator(T : T[])
{
	alias random_access_iterator!(T) iterator;
}

/******************************************************************************
 * Returns an element at a specified location in the array.
 *
 * Returns: 
 *     A value to the element subscripted in the argument. 
 *     If pos is greater than the size of the array, at throws an exception. 
 *
 * Params:
 *     array = Array object.
 *     pos   = The subscript or position number of the element to reference 
 *             in the array.
 * 
 * Example:
 * --------------------------------------
 * // array_at.d
 * voud main( )
 * {
 *    int[] v1;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 20 );
 * 
 *    int i = v1.at( 0 );
 *    int j = v1.at( 1 );
 *    dout << "The first element is " << i << endl;
 *    dout << "The second element is " << j << endl;
 * }
 * --------------------------------------
 *
 * Output:
 *         The first element is 10<br />
 *         The second element is 20
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *****************************************************************************/
T at(T)(inout T[] array, int pos)
{
	return array[pos];
}

unittest
{
	printf("test array.at\n\0");

	int[] array = [1,2,3];
	assert(array.at(0) == 1);
	assert(array.at(1) == 2);
	assert(array.at(2) == 3);
	assert(array == [1,2,3]);
}

/******************************************************************************
 * Returns last element of the array.
 *
 * Returns:
 *          The last element of the array. If the array is empty, the return 
 *          value is undefined.
 *
 * Params:
 *     array = Array object.
 *
 * Remarks: 
 *          When compiling with _SECURE_SCL 1, a runtime error will occur if 
 *          you attempt to access an element in an empty array. See Checked 
 *          Iterators for more information.
 *
 * Example:
 * -------------------------------------
 * // array_back.d
 * void main() {
 *    int[] v1;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 11 );
 * 
 *    int i = v1.back( );
 * 
 *    dout << "The last integer of v1 is " << i << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *          The last integer of v1 is 11
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *          front and back
 *****************************************************************************/
T back(T)(inout T[] array)
{
	version(_SECURE_SCL)
	{
		return array[$-1];
	}
	else
	{
		T result;
		if (!array.empty())
			result = array[$-1];
		return result;
	}
}

unittest
{
	printf("test array.back\n\0");

	int[] array = [1,2,3];
	int b = array.back();
	assert(b == 3);
	assert(array == [1,2,3]);
}


/******************************************************************************
 * Returns the number of elements that the array could contain without 
 * allocating more storage.
 *
 * Returns: The current length of storage allocated for the array.
 *
 * Params:
 *     array = Array object.
 *
 * Remarks: The member function resize will be more efficient if sufficient 
 *          memory is allocated to accommodate it. Use the member function 
 *          reserve to specify the amount of memory allocated. <br />
 *          This function is <b>deprecated</b>.
 *
 * Example:
 * ------------------------------------
 * // array_capacity.d
 * 
 * void main( )
 * {
 *    int[] v1;
 *    
 *    for (int i=0; i<16; ++i)
 *       v1.push_back( 1 );
 *    dout << "The length of storage allocated is "
 *         << v1.capacity( ) << "." << endl;
 * 
 *    v1.push_back( 2 );
 *    dout << "The length of storage allocated is now "
 *         << v1.capacity( ) << "." << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *         The length of storage allocated is 16.<br />
 *         The length of storage allocated is now 32.
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *         array.size and array.capacity
 ******************************************************************************/
// deprecated
size_t capacity(T)(inout T[] array)
{
	if (array.length <= 16)
		return 16;
	for (size_t i=32; true; i *= 2)
	{
		if (i > array.length)
			return i;
		if (i > (1 << 30))
			return size_t.max;
	}
	return size_t.max;
}

unittest
{
	printf("test array.capacity\n\0");

	int[] array = [];
	assert(array.capacity() == 16);

	int[] array1 = [1];
	assert(array1.capacity() == 16);

	int[] array2 = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16];
	assert(array2.capacity() == 16);

	int[] array3 = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16,17];
	assert(array3.capacity() == 32);
}


/******************************************************************************
 * Erases the elements of the array.
 *
 * Params:
 *     array = Array object.
 * 
 * Example:
 * ------------------------------------
 * // array_clear.d
 * 
 * void main( )
 * {
 *    int[] v1;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 20 );
 *    v1.push_back( 30 );
 * 
 *    dout << "The size of v1 is " << v1.size( ) << endl;
 *    v1.clear( );
 *    dout << "The size of v1 after clearing is " << v1.size( ) << endl;
 * }
 * ------------------------------------
 * 
 * Output:
 *         The size of v1 is 3<br />
 *         The size of v1 after clearing is 0
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 ******************************************************************************/
void clear(T)(inout T[] array)
{
	array.length = 0;
}

unittest
{
	printf("test array.clear\n\0");

	int[] array = [1,2,3];
	array.clear();
	assert(array.length == 0);
}


/******************************************************************************
 * Tests if the array is empty.
 *
 * Returns:
 *          true if the array is empty; false if the array is not empty.
 *
 * Params:
 *     array = Array object.
 *
 * Example:
 * ------------------------------------
 * // array_empty.d
 * 
 * void main( )
 * {
 *    int[] v1;
 * 
 *    v1.push_back( 10 );
 * 
 *    if ( v1.empty( ) )
 *       dout << "The array is empty." << endl;
 *    else
 *       dout << "The array is not empty." << endl;
 * }
 * ------------------------------------

 * Output:
 *         The array is not empty.
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *****************************************************************************/
bool empty(T)(inout T[] array)
{
	return 0 == array.length;
}

unittest
{
	printf("test array.empty\n\0");

	int[] array = [1,2,3];
	assert(array.empty() == false);
	int[] array1 = [];
	assert(array1.empty() == true);
}


/******************************************************************************
 * Returns a random-access iterator to the first element in the container.
 *
 * Returns: A random-access iterator addressing the first element in the array
 *          or to the location succeeding an empty array.
 *
 * Params:
 *     array = Array object.
 *
 * Example:
 * ------------------------------------
 * // array_begin.d
 * 
 * void main( )
 * {
 *    int[] c1;
 *    iterator!(int[]) c1_Iter;
 *    
 *    c1.push_back( 1 );
 *    c1.push_back( 2 );
 * 
 *    c1_Iter = c1.begin( );
 *    dout << "The first element of c1 is "<< *c1_Iter << endl;
 * 
 *    c1_Iter = 20;
 *    c1_Iter = c1.begin( );
 *    dout << "The first element of c1 is now "<< c1_Iter << endl;
 * }
 * ------------------------------------
 *
 * Output:  
 *         The first element of c1 is 1<br >
 *         The first element of c1 is now 20
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *         array.empty, array.erase, and array.push_back
 *****************************************************************************/
iterator!(T[]) begin(T)(inout T[] array)
{
	return iterator!(T[])(array, 0);
}

unittest
{
	printf("test array.begin\n\0");

	int[] array = [1,2,3];
	auto begin = array.begin();
	assert(begin == iterator!(int[])(array, 0));
}


/******************************************************************************
 * Returns a random-access iterator that points just beyond the end of the 
 * array.
 *
 * Returns:
 *          random-access iterator to the end of the array object. If the array
 *          is empty, array.end == array.begin.
 *
 * Params:
 *     array = Array object.
 *
 * Example:
 * ------------------------------------
 * // array_end.d
 *
 * void main( )
 * {
 *    int[] v1;
 *    iterator!(int[]) v1_Iter;
 *    
 *    v1.push_back( 1 );
 *    v1.push_back( 2 );
 * 
 *    for ( v1_Iter = v1.begin( ) ; v1_Iter != v1.end( ) ; v1_Iter++ )
 *       cout << v1_Iter.get << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *         1<br />
 *         2
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *****************************************************************************/
iterator!(T[]) end(T)(inout T[] array)
{
	return iterator!(T[])(array, array.length);
}

unittest
{
	printf("test array.end\n\0");

	int[] array = [1,2,3];
	auto end = array.end();
	assert(end == iterator!(int[])(array, 3));
}

/******************************************************************************
 * Removes an element in a array from specified position.
 *
 * Returns:
 *          An iterator that designates the first element remaining beyond any
 *          elements removed, or a pointer to the end of the array if no such
 *          element exists.
 *
 * Params:
 *          array = Array object.
 *          where = Position of the element to be removed from the array.
 *
 * Example:
 * ------------------------------------
 * // array_erase.d
 *
 * void main( )
 * {
 *    int[] v1;
 *    iterator!(int[]) Iter;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 20 );
 *    v1.push_back( 30 );
 *    v1.push_back( 40 );
 *    v1.push_back( 50 );
 * 
 *    dout << "v1 =" ;
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       dout << " " << *Iter;
 *    dout << endl;
 * 
 *    v1.erase( v1.begin( ) );
 *    dout << "v1 =";
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       dout << " " << *Iter;
 *    dout << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *         v1 = 10 20 30 40 50<br />
 *         v1 = 20 30 40 50
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *         empty, erase, and push_back
 *****************************************************************************/
iterator!(T[]) erase(T)(inout T[] array, iterator!(T[]) where)
{
	where.check_array(array);
	for (int i=where.get_pos(); i<array.length-1; ++i)
		array[i] = array[i+1];
	array.length = array.length - 1;
	return iterator!(T[])(array, where.get_pos());
}

unittest
{
	printf("test array.erase\n\0");

	int[] array = [1,2,3];
	iterator!(int[]) begin = array.begin();
	// DMD does not support this:
	// array.erase(array, begin);
	erase!(int)(array, begin);

	assert(array == [2,3]);
}


// 以下部分必须注释掉,DMD不允许这种重载,应该是个BUG

/******************************************************************************
 * Removes a range of elements in a array from specified positions.
 *
 * Returns:
 *          An iterator that designates the first element remaining beyond any
 *          elements removed, or a pointer to the end of the array if no such
 *          element exists.
 *
 * Params:
 *          array = Array object.
 *          first = Position of the first element removed from the array.
 *          last  = Position just beyond the last element removed from the
 *                  array.
 *
 * Example:
 * ------------------------------------
 * // array_erase.d
 *
 * void main( )
 * {
 *    int[] v1;
 *    iterator!(int[]) Iter;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 20 );
 *    v1.push_back( 30 );
 *    v1.push_back( 40 );
 *    v1.push_back( 50 );
 * 
 *    dout << "v1 =" ;
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       dout << " " << *Iter;
 *    dout << endl;
 * 
 *    v1.erase( v1.begin( ) );
 *    dout << "v1 =";
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       dout << " " << *Iter;
 *    dout << endl;
 *
 *    v1.erase( v1.begin( ) + 1, v1.begin( ) + 3 );
 *    cout << "v1 =";
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       cout << " " << *Iter;
 *    cout << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *         v1 = 10 20 30 40 50<br />
 *         v1 = 20 30 40 50<br />
 *         v1 = 20 50
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *         empty, erase, and push_back
 *****************************************************************************/
/*
iterator!(T[]) erase(T)(inout T[] array, iterator!(T[]) first, iterator!(T[]) last)
{
	return null;
}
*/


/******************************************************************************
 * Returns a reference to the first element in an array.
 *
 * Returns:
 *         The first element in the array object. If the array is empty, the
 *         return is undefined.
 *
 * Params:
 *     array = Array object.
 *
 * Remarks:
 *         When compiling with _SECURE_SCL 1, a runtime error will occur if you
 *         attempt to access an element in an empty array. See Checked
 *         Iterators for more information.
 *
 * Example:
 * ------------------------------------
 * // array_front.d
 * 
 * void main( )
 * {
 *    int[] v1;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 11 );
 * 
 *    int i = v1.front( );
 * 
 *    cout << "The first integer of v1 is "<< i << endl;
 * }
 * ------------------------------------
 * 
 * Output:
 *         The first integer of v1 is 10
 *  
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *          front and back
 *****************************************************************************/
T front(T)(inout T[] array)
{
	version(_SECURE_SCL)
	{
		return array[0];
	}
	else
	{
		if (!array.empty())
			return array[0];
		T result;
		return result;
	}
}

unittest
{
	printf("test array.front\n\0");

	int[] array = [1,2,3];
	int f = array.front();
	assert(f == 1);
	assert(array == [1,2,3]);
}


/******************************************************************************
 * Inserts an element or a number of elements or a range of elements into the
 * array at a specified position.
 *
 * Returns:
 *         The first insert function returns an iterator that points to the 
 *         position where the new element was inserted into the array.
 *
 * Params:
 *         array = Array object.
 *         where = The position in the array where the first element is
 *                 inserted.
 *         value = The value of the element being inserted into the array.
 *
 * Remarks:
 *         Any insertion operation can be expensive, see vector Class for a
 *         discussion of array performance.
 *
 * Example:
 * ------------------------------------
 * // array_insert.cpp
 * 
 * int main( )
 * {
 *    int[] v1;
 *    iterator!(int[]) Iter;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 20 );
 *    v1.push_back( 30 );
 * 
 *    dout << "v1 =" ;
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       dout << " " << Iter.get();
 *    dout << endl;
 * 
 *    v1.insert( v1.begin( ) + 1, 40 );
 *    dout << "v1 =";
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       dout << " " << Iter.get();
 *    dout << endl;
 *    v1.insert( v1.begin( ) + 2, 4, 50 );
 * 
 *    dout << "v1 =";
 *    for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
 *       dout << " " << Iter.get();
 *    dout << endl;
 * 
 *    v1.insert( v1.begin( )+1, v1.begin( )+2, v1.begin( )+4 );
 *    dout << "v1 =";
 *    for (Iter = v1.begin( ); Iter != v1.end( ); Iter++ )
 *       dout << " " << Iter.get();
 *    dout << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *         v1 = 10 20 30<br />
 *         v1 = 10 40 20 30<br />
 *         v1 = 10 40 50 50 50 50 20 30<br />
 *         v1 = 10 50 50 40 50 50 50 50 20 30
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *****************************************************************************/
iterator!(T[]) insert(T)(inout T[] array, iterator!(T[]) where, T value)
{
	where.check_array(array);
	array.length = array.length + 1;
	for(int i=array.length-1; i>where.get_pos(); i--)
		array[i] = array[i-1];
	array[where.get_pos()] = value;
	return iterator!(T[])(array, where.get_pos());
}

unittest
{
	printf("test array.insert\n\0");

	int[] array = [1,2,3];
	auto begin = array.begin();
	insert!(int)(array, begin, 4);
	assert(array == [4,1,2,3]);
}



/******************************************************************************
 * Deletes the element at the end of the array.
 *
 * Params:
 *         array = Array object.
 *
 * Example:
 * ------------------------------------
 * // array_pop_back.cpp
 * 
 * int main( )
 * {
 *    int[] v1;
 *    
 *    v1.push_back( 1 );
 *    dout << v1.back( ) << endl;
 *    v1.push_back( 2 );
 *    dout << v1.back( ) << endl;
 *    v1.pop_back( );
 *    dout << v1.back( ) << endl;
 * }
 *  
 * Output:
 *         1<br/>
 *         2<br/>
 *         1
 *  
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 * See_Also:
 *         push_back and pop_back
 *****************************************************************************/
void pop_back(T)(inout T[] array)
{
	if (array.length)
		array.length = array.length - 1;
}

unittest
{
	printf("test array.pop_back\n\0");

	int[] array = [1,2,3];

	array.pop_back();
	assert(array.length == 2);
	assert(array == [1,2]);

	array.pop_back();
	assert(array.length == 1);
	assert(array == [1]);

	array.pop_back();
	assert(array.length == 0);

	array.pop_back();
	assert(array.length == 0);
}


/******************************************************************************
 * Adds an element to the end of the array.
 *
 * Params:
 *         array = Array object.
 *         value = The element added to the end of the array.
 * 
 * Example:
 * ------------------------------------
 * // array_push_back.cpp
 * 
 * void main( )
 * {
 *    int[] v1;
 *    
 *    v1.push_back( 1 );
 *    if ( v1.size( ) != 0 )
 *       dout << "Last element: " << v1.back( ) << endl;
 * 
 *    v1.push_back( 2 );
 *    if ( v1.size( ) != 0 )
 *       dout << "New last element: " << v1.back( ) << endl;
 * }
 * ------------------------------------
 *
 * Output: 
 *         Last element: 1<br/>
 *         New last element: 2
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *         push_back and pop_back<br />
 *         accumulate, copy, and push_back<br />
 *         adjacent_difference and push_back<br />
 *         empty, erase, and push_back
 *****************************************************************************/
void push_back(T)(inout T[] array, T value)
{
	array ~= value;
}

unittest
{
	printf("test array.push_back\n\0");

	int[] array = [1,2,3];
	array.push_back(4);
	assert(array == [1,2,3,4]);

	array.push_back(5);
	assert(array == [1,2,3,4,5]);
}

/******************************************************************************
 * Specifies a new size for a array.
 *
 * Params:
 *         array = Array object.
 *         newsize = The new size of the array.
 *         value = The value of new elements added to the array if the new size
 *                 is larger that the original size. If the value is omitted,
 *                 the new objects are assigned the default value.
 *
 * Remarks:
 *         If the container's size is less than the requested size, _newsize,
 *         elements are added to the array until it reaches the requested size.
 *         If the container's size is larger than the requested size, the
 *         elements closest to the end of the container are deleted until the
 *         container reaches the size _newsize. If the present size of the
 *         container is the same as the requested size, no action is taken.
 *
 *         size reflects the current size of the array.
 *
 * Example:
 * ------------------------------------
 * // array_resize.d
 *
 * void main( )
 * { 
 *    int[] v1;
 *    
 *    v1.push_back( 10 );
 *    v1.push_back( 20 );
 *    v1.push_back( 30 );
 * 
 *    v1.resize( 4,40 );
 *    cout << "The size of v1 is " << v1.size( ) << endl;
 *    cout << "The value of the last object is " << v1.back( ) << endl;
 * 
 *    v1.resize( 5 );
 *    cout << "The size of v1 is now " << v1.size( ) << endl;
 *    cout << "The value of the last object is now " << v1.back( ) << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *         The size of v1 is 4<br />
 *         The value of the last object is 40<br />
 *         The size of v1 is now 5<br />
 *         The value of the last object is now 0
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *****************************************************************************/
void resize(T)(inout T[] array, size_t newsize, T value = T.init)
{
	array.length = newsize;
}

unittest
{
	printf("test array.resize\n\0");

	int[] array = [1,2,3];

	array.resize(cast(uint)5);
	assert(array == [1,2,3,0,0]);

	array.resize(cast(uint)2);
	assert(array == [1,2]);
}




/******************************************************************************
 * Reserves a minimum length of storage for a array object, allocating space if
 * necessary.
 *
 * Params:
 *         array = Array object.
 *         count = The minimum length of storage to be allocated for the array.
 *
 * Example:
 * ------------------------------------
 * // array_reserve.cpp
 * 
 * void main( )
 * {
 *    int[] v1;
 * 
 *    v1.reserve( 20 );
 * }
 * ------------------------------------
 *
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *****************************************************************************/
void reverse(T)(inout T[] array, size_t count)
{
	size_t oldlen = array.length;
	array.length = count;
	array.length = oldlen;
}

unittest
{
	printf("test array.reverse can't test\n\0");
}


/******************************************************************************
 * Returns the number of elements in the array.
 *
 * Returns:
 *         The current length of the array.
 *
 * Params:
 *         array = Array object.
 *
 * Example:
 * ------------------------------------
 * // array_size.d
 * 
 * voud main( )
 * {
 *    int[] v1;
 *    size_t i;
 *    
 *    v1.push_back( 1 );
 *    i = v1.size( );
 *    dout << "Vector length is " << i << "." << endl;
 * 
 *    v1.push_back( 2 );
 *    i = v1.size( );
 *    dout << "Vector length is now " << i << "." << endl;
 * }
 * ------------------------------------
 * 
 * Output:
 *         Vector length is 1.<br />
 *         Vector length is now 2.
 *  
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *
 * See_Also:
 *         size and capacity
 *****************************************************************************/
size_t size(T)(inout T[] array)
{
	return array.length;
}

unittest
{
	printf("test array.size\n\0");

	int[] array = [1,2,3];
	assert(array.size() == 3);

	int[] array1 = [1,2];
	assert(array1.size() == 2);
}


/******************************************************************************
 * Exchanges the elements of two arrays.
 *
 * Params:
 *         array = Array object.
 *         right = A array providing the elements to be swapped, or a array
 *                 whose elements are to be exchanged with those of the array
 *                 _left.
 *         left  = A array whose elements are to be exchanged with those of the
 *                 array _right.
 *
 * Example:
 * ------------------------------------
 * // array_swap.d
 * void main( )
 * {
 *    int[] v1, v2;
 * 
 *    v1.push_back( 1 );
 *    v1.push_back( 2 );
 *    v1.push_back( 3 );
 * 
 *    v2.push_back( 10 );
 *    v2.push_back( 20 );
 * 
 *    dout << "The number of elements in v1 = " << v1.size( ) << endl;
 *    dout << "The number of elements in v2 = " << v2.size( ) << endl;
 *    dout << endl;
 * 
 *    v1.swap( v2 );
 * 
 *    dout << "The number of elements in v1 = " << v1.size( ) << endl;
 *    dout << "The number of elements in v2 = " << v2.size( ) << endl;
 * }
 * ------------------------------------
 *
 * Output:
 *         The number of elements in v1 = 3<br />
 *         The number of elements in v2 = 2<br />
 *
 *         The number of elements in v1 = 2<br />
 *         The number of elements in v2 = 3<br />
 *  
 * Requirements:
 * ------------------------------------
 * import array;
 * ------------------------------------
 *****************************************************************************/
void swap(T)(inout T[] left, inout T[] right)
{
	T[] temp = left;
	left = right;
	right = temp;
}

unittest
{
	printf("test array.swap\n\0");

	int[] array1 = [1,2,3,4];
	int[] array2 = [4,3,2,1];
	array1.swap(array2);

	assert(array1 == [4,3,2,1]);
	assert(array2 == [1,2,3,4]);
}

import std.stdio;
void main()
{
	int[] a = [1,2,3];
	assert(a.at(0) == 1);
	auto i = a.begin();
	auto b = a.end();


	while(i != a.end())
	{
		printf("%d\n\0", i());
		i ++;
	}

	auto iter = a.begin();
	writefln(iter());
	iter = 5;
	writefln(a);
}

分享到:
评论
50 楼 oldrev 2007-04-07  
感觉 opAssign 用来设置值语意上有问题,比如:
List!(int).Iterator i1, i2;
i1 = i2; // 设置迭代器本身的值
i1 = 100;  // 设置i1指向的值为100
一个类型两种赋值语意?
49 楼 oldrev 2007-04-07  
遗憾的是数组的外部“成员函数”不能省略(),要不就更统一了
48 楼 oldrev 2007-04-07  
我的已经修改为 opAssign 和 opCall了,
这下我们各自的容器应该可以互动了
47 楼 qiezi 2007-04-07  
支持内置类型我倒不觉得应该像C++学习,我这里的数组也是类置类型,不过加上“Array Operations”,已经不需要find再去支持指针类型了,所以提领是完全可以避免的。

就算是一个指针,也可以利用D的数组把它转过来:
int* p = ...; 指向某缓冲区
int[] arr = p[0..3];

这时arr.ptr和p是指向同一位置的,不会产生内存拷贝,所以修改arr的内容也会到p指向的内存。
46 楼 qiezi 2007-04-07  
STL迭代器使用提领也是一种约定,D不支持它,也可以约定另一种嘛,可以用opCall,也可以加个get方法,只要都使用它就行了,没必要因为语法上不支持就吊死了。。

上面这个修改就是为了支持我现在的代码。。
45 楼 oldrev 2007-04-07  
引用
这个完全没有问题亚:
代码

   1. iterator find(iterator, T)(iterator first, iterator last, T value) 
   2. { 
   3.     auto i = first; 
   4.     while(i != last && i() != value) i++; 
   5.     return i; 
   6. } 
   7.  
   8. import std.stdio; 
   9. void main() 
  10. { 
  11.     int[] arr = [1,2,3]; 
  12.     writefln("array: ", arr); 
  13.  
  14.     auto r = find(arr.begin(), arr.end(), 2); 
  15.     writefln("pos: ", r.get_pos()); 
  16.  
  17.     erase!(int)(arr, r); 
  18.     writefln("array: ", arr); 
  19. } 


输出:
[5,2,3]
array: [1,2,3]
pos: 1
array: [1,3]

还有其它例子证明这个有问题吗?


范型算法是一个算法适应无数种容器,所有 STL 容器的迭代器都支持提领,所以一个 find 算法就能应用于所有容器包括内置数组身上,但是D没有提领就不行

上面的这个 find 函数被你改了,呵呵
44 楼 qiezi 2007-04-07  
前面的迭代器+2问题已经解决了。
43 楼 qiezi 2007-04-07  
上面输出第1行是另一段的,多拷了一行。。
42 楼 qiezi 2007-04-07  
这个完全没有问题亚:
iterator find(iterator, T)(iterator first, iterator last, T value)
{
	auto i = first;
	while(i != last && i() != value) i++;
	return i;
}

import std.stdio;
void main()
{
	int[] arr = [1,2,3];
	writefln("array: ", arr);

	auto r = find(arr.begin(), arr.end(), 2);
	writefln("pos: ", r.get_pos());

	erase!(int)(arr, r);
	writefln("array: ", arr);
}

输出:
[5,2,3]
array: [1,2,3]
pos: 1
array: [1,3]

还有其它例子证明这个有问题吗?
41 楼 oldrev 2007-04-07  
我的实现更新了
40 楼 oldrev 2007-04-07  
引用

好主意,可以实现成这样:
代码

   1. iter = 3; // 等价于C++的:*iter = 3; 
   2. int i = iter(); // 等价于C++的:int i = *iter; 


返回引用然后操作引用对象就不需要了,毕竟是C++专有的。


这样我个人感觉语意上有点问题,而且 iter() 的形式也不能让范型算法支持指针所表示的数组。

比如:

 
private IterType find(IterType, ValueType)(IterType first, IterType last, ValueType val)  
{  
    IterType i = first;  
    while(i != last && *i != val) ++i;    
    return i;  
}  


由于内置的数组是一个相当于 vector 的实现,但是却没有迭代器,因此感觉语言内部和外部的容器接口有点问题
39 楼 qiezi 2007-04-07  
我修改到代码里了,现在可以这样:
     auto iter = a.begin();  
     writefln(iter());  
     iter = 5;  
38 楼 qiezi 2007-04-07  
好主意,可以实现成这样:
iter = 3; // 等价于C++的:*iter = 3;
int i = iter(); // 等价于C++的:int i = *iter;

返回引用然后操作引用对象就不需要了,毕竟是C++专有的。
37 楼 oldrev 2007-04-07  
必须用到函数签名这就是问题所在了,不一定所有人都同意叫get/set,除非在语言标准里定下来。

好像实现重载提领与现在的语言并不冲突呀

或者实现为 opCall?
36 楼 qiezi 2007-04-07  
指针在D里面是应该避免使用的,尽量用于底层代码。

C++的方式:
iter = vec.begin();
*iter = 3;
int a = *iter;
int& b = *iter;
b = 5;

D里面可以改成set/get方法:
iter = array.begin();
iter.set(3);
int a = iter.get();
iter.set(5);

风格更统一一些。
35 楼 oldrev 2007-04-07  
D实现iterator有个问题是D不支持重载指针提领,很难实现STL风格的iterator。而且与 C++ 不同的是指针和数组是两种类型,真是麻烦。
34 楼 oldrev 2007-04-07  
我的双向链表模板类:
http://oldrev.iteye.com/admin/show/68748
33 楼 oldrev 2007-04-07  
我现在正在写个双向链表类,等一下我贴出来玩玩
32 楼 oldrev 2007-04-07  
那要是v1_Iter+=2把end跳过了怎么办?
标准是人定的,错误也是人犯的。

链表的iterator也是可以比较大小的,就看怎么实现了。


双向链表的迭代迭代器是双向迭代器,不支持大小比较,而且也不支持 += 2。
链表中的节点在堆中的位置完全是随机的,后加入的节点的地址不一定比老节点大。
STL 是数据结构和算法实现的典范,值得好好学习。
31 楼 qiezi 2007-04-07  
通常+=2也最多只会到end,所以不会跳过。我的实现没有考虑到这个,有时间还得改改。

相关推荐

    C++ STL vector 容器介绍

    C++ STL(Standard Template Library,标准模板库)是C++编程语言中不可或缺的一部分,它提供了一组高效且灵活的算法、容器和迭代器。在STL中,`vector`是一种非常重要的容器,它是一个动态数组,允许在任意位置进行...

    STL容器之array和vector.zip

    2. 成员函数:`std::array`提供了一系列的成员函数,如`size()`用于获取大小,`data()`返回原始数组的指针,以及重载的`[]`操作符用于访问元素。 3. 类型安全:由于`std::array`的大小是模板参数的一部分,所以在...

    走进stl (using stl)

    在这个例子中,`std::vector`作为STL的容器,替代了原始数组,`push_back`方法用于添加元素,而范围for循环则简化了求平均值的过程,无需手动管理索引。 总的来说,尽管STL的语法可能对初学者来说较为复杂,但它的...

    stl 小例子

    STL,全称为Standard Template Library(标准模板库),是C++编程语言中的一部分,它提供了一组高效、灵活且可重用的容器、迭代器、算法和函数对象(仿函数)。STL的主要目标是提高代码的简洁性、可读性和性能。在...

    [中英文]STL参考手册

    例如,`vector`的插入和删除操作在大多数情况下比原始数组更快,因为它会自动处理内存管理和元素移动。 STL的文档详细介绍了每个组件的使用方法、接口以及注意事项,是学习和使用STL的重要参考资料。对于开发者来说...

    源码 STL1.0库

    STL的算法库包含了一组通用的函数模板,用于执行各种常见操作,如排序(`std::sort`)、查找(`std::find`)、复制(`std::copy`)、合并(`std::merge`)等。这些算法可以作用于任何容器,通过迭代器来访问元素,...

    数组(一维、二维、三维)的动态申请及用vector的表示方法

    ### 数组(一维、二维、三维)的动态申请及用vector的表示方法 #### 一、变长一维数组 变长数组是指在编译时不能确定数组长度,而是在程序运行时需要动态分配内存空间的数组。下面详细介绍如何在C++中实现变长一维...

    STL-基础数据类型的基本用法

    STL,全称为Standard Template Library(标准模板库),是C++编程语言中的一部分,它提供了一组高效且灵活的数据结构和算法。STL的核心概念包括容器、迭代器、算法和函数对象,这些组件共同构成了一个强大的工具箱,...

    C++ STL库知识总结

    C++ STL库是C++标准库的一个重要组成部分,它提供了丰富的数据结构和算法,极大地提升了C++编程的效率和灵活性。以下是对C++ STL库知识的详细总结。 首先,STL(Standard Template Library,标准模板库)包含了六大...

    C++程序设计教学课件:Ch5 Array, String and Vector.pdf

    向量(Vector)是C++标准模板库(STL)中的一个动态数组容器。向量提供了比传统数组更高级的功能,如动态内存管理、大小的自动调整、成员访问和迭代器支持。声明向量时,需要包含头文件 `&lt;vector&gt;` 并指定存储的数据...

    数据结构C++描述(STL)

    常见的容器有数组(`std::array`)、向量(`std::vector`)、列表(`std::list`)、链表(`std::forward_list`、`std::list`)、集合(`std::set`、`std::unordered_set`)、映射(`std::map`、`std::unordered_map`...

    STL、贪心.zip_acm 算法

    1. 容器:STL提供了多种类型的容器,如数组(array)、向量(vector)、列表(list)、链表(forward_list)、双链表(list)、集合(set)、映射(map)、无序集合(unordered_set)和无序映射(unordered_map)。...

    cffect stl eg(原版)pdf

    - “swap技巧”是一种有效减少`std::vector`或`std::string`多余容量的方法。 - 这有助于提高程序的整体性能。 **描述:** - 通过交换两个容器的内部数据,可以有效地将一个容器的容量减小到其实际大小。 - 示例...

    VC.add.programming.array.list.rar_vc list

    它提供了一组方法来操作这些元素,包括添加、删除、访问和修改。例如,我们可以使用`push_back()`方法向数组列表末尾添加元素,使用`pop_back()`方法移除最后一个元素,使用`size()`获取元素数量,以及通过索引访问...

    C++程序设计教学课件:CHAPTER 11 THE STANDARD TEMPLATE LIBRARY.ppt

    3. **算法**:STL提供了一组广泛的算法,这些算法不依赖于特定的容器实现,可以对容器中的元素进行操作,如排序(sort)、查找(find)、拷贝(copy)、删除(remove)等。这些算法大大简化了复杂操作的编写,提高了...

    STL

    STL,全称为Standard Template Library(标准模板库),是C++编程语言中不可或缺的一部分,它为程序员提供了高效且可重用的数据结构和算法。STL的核心理念是泛型编程,这意味着它能处理不同类型的对象,提高了代码的...

    Algorithm-tstl.zip

    1. **容器**:容器是一组对象的集合,提供了对这些对象的管理方式。例如,`Array`(数组)、`Vector`(动态数组)、`List`(双链表)、`Set`(集合)和`Map`(映射)等。这些容器提供了丰富的操作接口,如插入、删除...

    test_stl

    它提供了一组高效、可重用的容器、迭代器、算法和函数对象,极大地提高了C++程序员的开发效率。JavaScript,另一方面,是Web前端开发的主导语言,通常与HTML和CSS一起用于构建交互式的网页应用。尽管JavaScript自身...

    c + + 试 题 及 答 案

    题目给出了一组字符串的定义和比较操作: ```cpp char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str6 = "abc"; cout ...

    几本语言类的数据

    而“STL编程指南”则专注于C++编程,STL是C++的一个重要组成部分,提供了一组高效的数据结构(如vector、list、set)和算法(如排序、查找),极大地提高了代码的可读性和效率。 在编程领域,掌握算法和数据结构是...

Global site tag (gtag.js) - Google Analytics