`
qiezi
  • 浏览: 492170 次
  • 性别: 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);
}

分享到:
评论
30 楼 qiezi 2007-04-07  
这种主要是因为类吧,比如:
ClassA a = new ClassA;
a = new ClassA;

如果允许那种行为,可以这种简单的赋值都成问题了。

struct和c++的struct/class比较像一些,我倒是建议允许上面这种语法,这不就是operator=嘛。
29 楼 h_rain 2007-04-07  
那要是v1_Iter+=2把end跳过了怎么办?
标准是人定的,错误也是人犯的。

链表的iterator也是可以比较大小的,就看怎么实现了。
28 楼 oldrev 2007-04-07  
刚才我尝试着写链表,才注意到一个大特性:opAssign 的参数不能为左值或可以隐式转换为左值的类型,比如:
struct S
{
    int x;

    S opAssign(S rhs) // 错误
    {
        x = rhs.x;
        return *this;
    }
}

我想这个限制的原因是因为GC要跟踪对象引用的转移吧
27 楼 oldrev 2007-04-07  
引用
呵呵,你还在呢:)
那这么说,end仅仅只能被用于边界判断了?
我没怎么看过设计模式,现在补补课吧,呵呵。
代码

   1. int[] array = [1,2,3]; 
   2. for ( auto v1_Iter = array.begin( ) ; v1_Iter < array.end( ) ; v1_Iter++ ) 
   3.     v1_Iter.get; 


这么写似乎更舒服些


v1_Iter != array.end() 是标准写法,如果是链表的 iterator 就不能比较大小了
26 楼 qiezi 2007-04-07  
一般是这么写:
int[] array = [1,2,3];  
for ( auto v1_Iter = array.begin( ) ; v1_Iter != array.end( ) ; v1_Iter++ )  
v1_Iter.get;


上面这个语法应该叫作“Array Operations”,我猜的。。D主页上Future里面有一项,我猜就是这个。

你可以写成:
at(array, 0);
或
array.at(0);
25 楼 h_rain 2007-04-07  
对了,
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]);
}


这个里面的at函数在语法上与array进行了组合,成为array.at(),在D语言中这个用法叫什么?感觉怪怪的:)
24 楼 h_rain 2007-04-07  
呵呵,你还在呢:)
那这么说,end仅仅只能被用于边界判断了?
我没怎么看过设计模式,现在补补课吧,呵呵。
    int[] array = [1,2,3];
    for ( auto v1_Iter = array.begin( ) ; v1_Iter < array.end( ) ; v1_Iter++ )
        v1_Iter.get;

这么写似乎更舒服些
23 楼 qiezi 2007-04-07  
可以使用back来获取最后一个元素。
22 楼 qiezi 2007-04-07  
end是不能用于取值的,取代它的是rbegin,我这里没有实现它
21 楼 h_rain 2007-04-07  
代码如下:
    int[] array = [1,2,3];
    auto end = array.end();
    printf("%d",end.get);

我不知道end.get这么用在理论上对不对,但在这个实现上会有异常。
array.end()在迭代器模式中,只能被用于判断边界吗?不可以用于取值吗?C++ STL是怎么处理的?
20 楼 qiezi 2007-04-06  
size不要也可以,无伤大雅。

随机访问迭代器的确是有[]操作符,有时间再补上吧,真去做得完善了,那又是写一整套STL了。迭代器是STL六大组件之一吧。
19 楼 oldrev 2007-04-06  
还有个小小的建议,size 就不用了,风格不一样,D里都是用 length 的
18 楼 oldrev 2007-04-06  
引用

这2个方法不应该是iterator的吧?应该是容器的。。


这个也是伤脑筋的问题,STL 的随机访问迭代器是有[]操作符的,用起来感觉像容器。但问题是既然实现了 opIndex,那要不要实现opSlicing?甚至 opApply?用foreach对迭代器进行迭代语意上合理吗?

欢迎讨论!
17 楼 oldrev 2007-04-06  
参见这篇文章:
http://www.boost.org/libs/iterator/doc/new-iter-concepts.html
boost 中的新 iterator 概念,比 STL 的更合理
16 楼 qiezi 2007-04-06  
更新了,实现了大部分方法,除了assign, get_allocator, max_size, rbegin, rend.
15 楼 qiezi 2007-04-06  
链表缓一下吧,数组已经发现许多问题,隐式模板类型推导不完善,做出来也不好用。。
14 楼 qiezi 2007-04-06  
这2个方法不应该是iterator的吧?应该是容器的。。
13 楼 oldrev 2007-04-06  
写个链表吧,D还没这个
12 楼 oldrev 2007-04-06  
iterator 还缺少  opIndex, opApply 等
11 楼 qiezi 2007-04-06  
改成struct了,晚上增加一些方法一起传上来。

还要做个效率测试,看看这个会不会比直接用下标低效,我想如果用inline编译的话应该不会有影响。。

相关推荐

Global site tag (gtag.js) - Google Analytics