可变参数函数,如何使它更安全更有意义?
我是C ++的新手,我的第一语言是中文,所以我的英文单词可能是无意义的,首先抱歉。 我知道有一种方法可以编写一个可变参数的函数,每个调用的数字或类型可能不同,我们可以使用va_list,va_start和va_end的宏。 但是大家都知道,这是C风格。 当我们使用宏时,我们将失去类型安全和自动推理的好处,然后尝试使用它来处理C ++模板。 我的工作如下:
#include<iostream>
#include<vector>
#include<boost/any.hpp>
struct Argument
{
typedef boost::bad_any_cast bad_cast;
template<typename Type>
Argument& operator,(const Type& v)
{
boost::any a(v);
_args.push_back(a);
return *this;
}
size_t size() const
{
return _args.size();
}
template<typename Type>
Type value(size_t n) const
{
return boost::any_cast<Type>(_args[n]);
}
template<typename Type>
const Type* piont(size_t n) const
{
return boost::any_cast<Type>(&_args[n]);
}
private:
std::vector<boost::any> _args;
};
int sum(const Argument& arg)
{
int sum=0;
for(size_t s=0; s<arg.size(); ++s)
{
sum += arg.value<int>(s);
}
return sum;
}
int main()
{
std::cout << sum((Argument(), 1, 3, 4, 5)) << std::endl;
return 0;
}
我觉得这很难看,我想有一种方法可以做得更好? 谢谢,对于语言错误感到抱歉。
你可以做这样的事情:
template <typename T>
class sum{
T value;
public:
sum ()
: value() {};
// Add one argument
sum<T>& operator<<(T const& x)
{ value += x; return *this; }
// to get funal value
operator T()
{ return value;}
// need another type that's handled differently? Sure!
sum<T>& operator<<(double const& x)
{ value += 100*int(x); return *this; }
};
#include <iostream>
int main()
{
std::cout << (sum<int>() << 5 << 1 << 1.5 << 19) << "n";
return 0;
}
这种技术(运算符重载和类流函数类)可以解决可变参数的不同问题,而不仅仅是这一个。 例如:
create_window() << window::caption - "Hey" << window::width - 5;
// height of the window and its other parameters are not set here and use default values
几年前,我在DDJ.com上撰写了一篇关于类型安全printf C ++实现的文章。 它可以处理可比较的问题。 也许这有帮助。
请参阅http://www.ddj.com/cpp/184401999
经过一番思考,我找到了一种使用类型列表的方法。 您不需要这种类型的any
类型,并且您的代码变得类型安全。
它基于构建一个包含头部(已知类型)和尾部的模板结构,该头部也是一个类型列表。 我添加了一些语法糖使它更直观:使用像这样:
// the 1 argument processing function
template< typename TArg > void processArg( const TArg& arg ) {
std::cout << "processing " << arg.value << std::endl;
}
// recursive function: processes
// the first argument, and calls itself again for
// the rest of the typelist
// (note: can be generalized to take _any_ function
template< typename TArgs >
void process( const TArgs& args ) {
processArg( args.head );
return process( args.rest );
}
template<> void process<VoidArg>( const VoidArg& arg ){}
int main() {
const char* p = "another string";
process( (arglist= 1, 1.2, "a string", p ) );
}
这里是参数传递框架:
#include <iostream>
// wrapper to abstract away the difference between pointer types and value types.
template< typename T > struct TCont {
T value;
TCont( const T& t ):value(t){}
};
template<typename T, size_t N> struct TCont< T[N] > {
const T* value;
TCont( const T* const t ) : value( t ) { }
};
template<typename T> struct TCont<T*> {
const T* value;
TCont( const T* t ): value(t){}
};
// forward definition of type argument list
template< typename aT, typename aRest >
struct TArgList ;
// this structure is the starting point
// of the type safe variadic argument list
struct VoidArg {
template< typename A >
struct Append {
typedef TArgList< A, VoidArg > result;
};
template< typename A >
typename Append<A>::result append( const A& a ) const {
Append<A>::result ret( a, *this );
return ret;
}
//syntactic sugar
template< typename A > typename Append<A>::result operator=( const A& a ) const { return append(a); }
} const arglist;
// typelist containing an argument
// and the rest of the arguments (again a typelist)
//
template< typename aT, typename aRest >
struct TArgList {
typedef aT T;
typedef aRest Rest;
typedef TArgList< aT, aRest > Self;
TArgList( const TCont<T>& head, const Rest& rest ): head( head ), rest( rest ){}
TCont<T> head;
Rest rest;
template< typename A > struct Append {
typedef TArgList< T, typename Rest::Append<A>::result > result;
};
template< typename A >
typename Append< A >::result append( const A& a ) const {
Append< A >::result ret ( head.value, (rest.append( a ) ) );
return ret;
}
template< typename A > typename Append<A>::result operator,( const A& a ) const { return append(a); }
};
链接地址: http://www.djcxy.com/p/43115.html
上一篇: variable parameter function, how to make it type safe and more meaningful?