进行初步设计:
涉及的问题是:
template<typename T>
class Sin
{
public:
T operator()(T x){...};
};
Sin<float> sin;
float x;
sin(x);
Sin<double> sin;
float x;
sin(x);//error
///////////////////////////////////////////////////
class Sin
{
public:
template<typename T>
T operator()(T x){...};
};
Sin sin;
float x;
sin(x);
Sin sin;
double x;
sin(x);
尽管看上去区别不大,但是设计库的时候,会有很大,或非常大的差别。
比较:
第一种会方便开发。
第二种会方便用户使用。
后面又进行了试探性的设计,还是决定从方便开发的角度选第一种class template, 选用第二种在开发中会带来一定的困难,甚至面读系统将来需要增加新的功能时,自己没有信心完成设计。
后面又进行了试探性的设计,还是决定从方便开发的角度选第一种class template, 选用第二种在开发中会带来一定的困难,甚至面读系统将来需要增加新的功能时,自己没有信心完成设计。
做了一些试探性的设计,发现确实class template 更好:
template <typename T>
class objective_function
{
public:
typedef T value_type;
virtual ~objective_function();
virtual size_t dim() const =0;
virtual T operator() (const T * x, T * g=0)const =0;
virtual bool progress(int n, const T* x, T fx, const T * g,
T gnorm) const;
// 设计过于复杂
template<typename T, class FunObj>
class minimizer
{
public:
typedef T value_type;
virtual void do_get_direction(array1d<T>& d);
void main_loop(array1d<T>& x)
{
array1d<T> d(x.size());
T f;
f=FunObj(x, g);
progress();
while(1)
{
do_get_direction(d);
T t=get_initial_step();
do_line_search(x, t, f, g, x_new, f_new, g_new);
if(!(bool continue=progress()))
break;
if(bool stop=stop_if_optimal(g, f))
break;
}
}
virtual T do_get_step(T initial);
virtual T get_initial_step();
virtual void do_line_search(array1<T>& x, T& t, T& f, array1d<T>& g);
// virtual bool stop_if_optimal(const array1d<T>&g, T f);
virtual bool progress();
};
// FunObj is FunObj<T>
template<typename T, class FunObj>
class minimizer
{
public:
typedef T value_type;
FunObj<T> 本身含有T,这两个T 不是重复了?
解决方法1: 类似的,可以这样写 把模板写成这样感觉很变态,难以阅读,不过确实有效
// 优点:保证T 与 FunObj<T> 完全一致
template <typename T, template<typename> class FunObj>
class minimizer<T, FunObj<T> >
// 类似的,可以这样写
// std::allocator<T>
template <template<class, class > class C, typename T>
void test(C<T,std::allocator<T> >& A, T x, int N)
{
T v;
v=A[0]*x;
cout<<v<<endl;
}
youdian: // 优点明显:灵活使用,<int, FucObj<float> > <double, FucObj<float> >
// 缺点也很明显: 比如涉及:1.0, FuncObj<float> , 1.0 默认的是double类型, 用户没有想把这些类都变成double类型,只是写掉了一个f, 1.0f, 但编译器不会报告错误
template <T1, T2>
struct larger_type
{
typedef T1 type;
}
template <>
struct larger_type<float, double>
{
typedef double type;
}