荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: sephiroth (Dreams Come True), 信区: Program
标 题: C++技巧:将算符和函数同时保存在一个数组[转载]
发信站: 荔园晨风BBS站 (Fri Jan 3 21:45:15 2003), 站内信件
在标准模板库(STL)中,算符是经常使用而又新推出的一个概念。一个算符即是具
有函数特性的对象。既然它作为一个对象,算符包括内容,以及与算符相关联的东
西。
由于能够被赋予一定数量的元素,算符和函数非常有用。开发人员在编程过程中通
常需要把多个转换结果传递给一定范围的元素。其中一些转换属于函数,一些转换
属于算符。然而,要把函数和算符同时保存一个数组是不可能的,因为函数和算符
不能共用一个基类。
我们可以通过生成一个封装类来解决以上的问题,这一封装类既包括函数又包括算
符。你可以使用任一容器来容纳它们,包括STL容器或象C中的数组。
保存在数组中的每一个函数/算符需要一个传入参数并返回一个值。这是因为函数
/算符被赋予一个元素并返回一个值。
下面即是一个范例,这一范例能够将多种转换结果赋予一个字符串的数组。
#include
<string>
#include <functional>
#include <deque>
#include <iostream>
// truncates a string - you pass the max. nr. of chars a string can
have;
// then, for each string you pass,
// it returns a string with the nr. of chars <= max. nr. of chars
class truncate_string
: public std::unary_function< const std::string &,std::string>
{
public:
truncate_string( int nMaxChars)
: m_nMaxChars( nMaxChars) {}
std::string operator()( const std::string & strSource)
{
std::string strTruncated = strSource.substr( 0,m_nMaxChars);
return strTruncated;
}
private:
int m_nMaxChars;
};
// surrounds a string - with the two chars you pass at construction
class surround_string
: public std::unary_function< const char *, std::string>
{
public:
surround_string( char chFirst, char chLast)
: m_chFirst( chFirst), m_chLast( chLast) {}
std::string operator()( const char * strSource)
{
std::string strSurrounded;
strSurrounded += m_chFirst;
strSurrounded += strSource;
strSurrounded += m_chLast;
return strSurrounded;
}
private:
char m_chFirst;
char m_chLast;
};
std::string first_half( const char * strSource)
{
std::string strHalf = strSource;
size_t nLen = strHalf.length();
nLen = (nLen + 1) / 2;
strHalf = strHalf.substr( 0, nLen);
return strHalf;
}
std::string second_half( const char * strSource)
{
std::string strHalf = strSource;
size_t nHalfLen = strHalf.length() / 2;
strHalf = strHalf.substr( nHalfLen);
return strHalf;
}
// trims leading & trailing spaces
std::string trim( const std::string & strSource)
{
int nLen = ( int)strSource.length();
int idxFirst = 0;
int idxLast = nLen - 1;
while ( (idxFirst < nLen) && isspace( strSource[idxFirst]))
{ idxFirst++; }
while ( ( idxLast >= idxFirst) && isspace( strSource[idxLast]))
{ idxLast--; }
if ( idxLast >= idxFirst)
{
std::string strTrimmed = strSource.substr( idxFirst,
idxLast + 1 -
idxFirst);
return strTrimmed;
}
else
{
// this string contains only spaces
return std::string();
}
}
void test_functions_array()
{
typedef function_base< const char *, std::string>
StringTransformer;
typedef std::deque< StringTransformer*>
StringTransformersArray;
typedef std::deque< std::string> StringsArray;
StringTransformersArray aTransformers;
StringsArray aDescriptions;
aTransformers.push_back( functor_elem( surround_string('[', ']')
));
aDescriptions.push_back( "Surrounding string with []");
aTransformers.push_back( functor_elem( surround_string('{', '}')
));
aDescriptions.push_back( "Surrounding string with {}");
aTransformers.push_back( functor_elem( surround_string('<',
'>') ));
aDescriptions.push_back( "Surrounding string with
<>");
aTransformers.push_back(
convert_functor_elem< const char *, std::string>(
truncate_string( 10) ));
aDescriptions.push_back( "Truncate string to 10 chars");
aTransformers.push_back(
convert_functor_elem< const char *, std::string>(
truncate_string( 15) ));
aDescriptions.push_back( "Truncate string to 15 chars");
aTransformers.push_back( function_elem( first_half));
aDescriptions.push_back( "Returning first half of
string");
aTransformers.push_back( function_elem( second_half));
aDescriptions.push_back( "Returning second half of
string");
aTransformers.push_back(
convert_function_elem< const char *,
std::string>( trim));
aDescriptions.push_back( "Trims leading and trailing
spaces");
const char * aTestStrings[] =
{
" First string to test. ",
" Second string, that is.",
"A more complicated string, a little bigger than
the rest",
"Ok.",
" Last string. End. ",
NULL
};
const char ** pstrTest = aTestStrings;
while ( pstrTest[ 0] != NULL)
{
StringTransformersArray::const_iterator
itFirst = aTransformers.begin(),
itLast = aTransformers.end();
StringsArray::const_iterator itDescription =
aDescriptions.begin();
const char * strSource = pstrTest[ 0];
std::cout << "Original string: '"
<< strSource << "'" << std::endl <<
std::endl;
while ( itFirst != itLast)
{
std::cout
<< "Transformation:
" << *itDescription << std::endl;
std::cout
<< "Transformed
string: '"
<< ( **itFirst)(
strSource) << "'" << std::endl << std::endl;
++itFirst;
++itDescription;
}
std::cout << "----------------"
<< std::endl << std::endl;
pstrTest++;
};
}
int main(int argc, char* argv[])
{
test_functions_array();
return 0;
}
以下是说明如何在数组中插入元素:
1.functor_elem( adapter_function):从适配函数生成一个算符封装。
2.convert_functor_elem( adapter_function):生成一个包含适配函数的算符封装
,这一函数包含一个变量并返回一个值。
3.function_elem( function):从相应函数生成一个算符封装。
4.convert_function_elem( function):从相应函数生成一个算符封装,与
convert_functor_elem相类似。
注意,在你的数组中,你必须把指针指向一个基类(function_base< Type,
ReturnType>)。所以,它们会生动通过”new”来生成。你必须在结束时删除这一
指针。我们建议你你采用一个指针变量,这样可以很容易地删除掉。
下面是把函数/算符集中在一个数组中的代码示例。
template<class Type, class ReturnType = void>
class function_base
{
public:
virtual ~function_base() {}
virtual ReturnType execute( Type) = 0;
ReturnType operator()( Type value) { return execute( value); }
};
template<
class Functor,
class Type = typename Functor::argument_type,
class ReturnType = typename Functor::result_type >
class functor_wrapper_t
: public function_base< Type, ReturnType>
{
public:
functor_wrapper_t( Functor func)
: m_func( func) {}
ReturnType execute( Type value) { return m_func( value); }
private:
Functor m_func;
};
// TypeTo, ReturnTypeFrom - the types we're converting to/from;
//
// for instance, the function prototype might not be exactly
// 'ReturnType function( const Type &)', but rather have another
// type as argument - one type that 'Type' can be converted to, and
// return a type that can be converted to 'ReturnType'
template< class Type, class ReturnType, class TypeTo = Type, class
ReturnFrom =
ReturnType>
class function_wrapper_t
: public function_base< Type, ReturnType>
{
typedef ReturnFrom (* function_type)( TypeTo);
public:
function_wrapper_t( function_type func)
: m_func( func) {}
ReturnType execute( Type value) { return ( ReturnType)m_func( (
TypeTo)value); }
private:
function_type m_func;
};
template< class Functor>
functor_wrapper_t< Functor> * functor_elem( Functor func)
{ return new functor_wrapper_t< Functor>( func); }
template< class Type, class ReturnType, class Functor>
functor_wrapper_t< Functor, Type, ReturnType> *
convert_functor_elem( Functor
func)
{ return new functor_wrapper_t< Functor, Type, ReturnType>( func); }
template< class Type, class ReturnType>
function_wrapper_t< Type, ReturnType> *
function_elem( ReturnType (* function)( Type))
{ return new function_wrapper_t< Type, ReturnType>( function); }
template< class Type, class ReturnType, class TypeTo, class
ReturnTypeFrom>
function_wrapper_t< Type, ReturnType, TypeTo, ReturnTypeFrom>
*
convert_function_elem( ReturnTypeFrom (* function)(
TypeTo))
{ return new function_wrapper_t< Type, ReturnType, TypeTo,
ReturnTypeFrom>(
function); }
--
那一年,我生命中吹过的风,在这里轻轻地转了一个弯... ...
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.44.81]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店