上文http://blog.csdn.net/zy498420/archive/2010/11/09/5998427.aspx提到的“播种”之法需要你手动指定目标类型,稍微还是有点罗嗦(et_seed<std::string>,字母还是挺多的),然而为什么需要指定呢?
原因:如果不指定,最终生成的树可能根本不知道应该转换为何种类型,dest_type 未知。
那么把 inline operator binary_op::dest_type () const;
改为 template <typename T> inline operator binary_op::T() const;不行吗,在“=”的时候自动选择T的类型?
答案:不行。“=”左边的操作对象可能有多种单参数构造函数。以std::string为例,T可以为string也可以为const char*,他们的函数重载决议的地位是平等的,这时候就产生了二义 性,编译器不知道该如何选择。
那么我们就一定要一开始就显示指定吗目标类型?
答案:不一定。我们只需要保证第一棵树的构造时,目标类型能被指定。
这下问题的本质就出来了:如果种子不携带目标类型信息,而且第一次的操作对象恰好不是目标类型,那么这棵树就永远也没有机会得知目标类型了。
strb = et_seed<std::string>() + “1234567890"+ str1+ str2 + string("3 ");
如上,第一步et_seed<std::string>() + “1234567890",假设et_seed不携带信息std::string,et_seed<??>() + “1234567890"的结果根本不知道他需要转化成string!
那么话又说回来,而且第一次的操作对象是目标类型(我想这其实也是多数情况),那么我们就可以不指定而靠模板函数自动读取操作对象的类型来获得目标类型了。
strb = et_seed<??>() + str1+“1234567890"+ str2 + string("3 ");
我干脆给它取了个新名字any_seed
struct any_seed: et_seed<void>{};
然后其它地方修修补补,帮助函数重载决议就搞定了。
然而我们不能寄希望用户总是明智的,如果用户strb = any_seed() + “1234567890"+ str1+ str2 + string("3 ");这样的情况下使用any_seed,生成的树将错误的认为目标类型是char [11]而不是string,直到最后该赋值了编译器才发现不能对char [11]做+=操作,然后口吐莲花,喷出500多K的超长错误信息(最终生成的树类型名字可能长达几个屏幕)......
我可不想被用户骂死。
终极方案出炉:种子皮
template <typename D>
inline _et_private::binary_op<D, any_seed, D>
any_seeder(const D& arg)
{return _et_private::binary_op<D, any_seed, D> (any_seed(), arg);}