@溪流
1.
这是C++的缺陷…… 当初可能没想到模板会被这么用,所以模板的功能其实还比较弱。
即使比较弱,也比java和C#强大,它是真正的代码生成器……
C#的模板有一些约束,java的根本就是垃圾……
所以,模板还是很复杂的……
更本质的说,其实体现的是一种ducking type,以单一函数作为组件之间交互的接口,而不是整个类型。ruby、python、lua这种动态类型语言都支持ducking type。而C++的模板只支持编译时的ducking type。
C++社区给这种使用方式取了一个新的名字,叫concepts……
ducking type可能属于新东西,而且很可能是意外产物(比如C++、python、lua;ruby好像是设计之初就考虑到这种用法),所以没有提供专门的、显示的通过短小的代码(比如interface声明)就可以表达的方式。只能通过文档了……
说穿了,那些抵触这种设计的,要么是偷懒不想看文档,要么是已经学会OO就不想学任何其他新事物,要么就是理解能力不够……
心里疙瘩放下吧……
1.1. 虽然没有专门的语法支持,但语言还是会检查的,比如C++编译时出错,其他3个语言运行时出错。
1.2. 比如python标准库中,序列就没有单独的size()成员。所有的序列都通过len得到长度。已经开始向这种思想靠拢了。
1.3. stl也这么多年了……
2
我对0依赖的看法不是"难",而是"通常没有必要"。
应该尽可能复用已有的优秀的代码。
尽可能向已有的,还过得去不算垃圾的标准靠拢,而不是自己独立发明一套,结果在实际应用中无法融合。
当然,这和练习编程技巧相抵触……
所以我想提出一些建议,既可以练习;并且练习的结果是可以真正派上用场的。
比如,你可以考虑实现这样一个函数:
int vprintf_parse(void (*handler)(const char* s,void* context),void* context
const char* format, va_list arg );
按vprintf的标准去解析format与arg。每处理完一个%就调用handler一次。
由handler去考虑将s"输出"到哪里。
这样的话,vprintf_parse就可以用于很多很多地方:传递不同的hanlder给它就行。
当然,你也可以用它来实现string.format。 但一定要将vprintf_parse暴露出来,否则窝在string.format中太暴殄天物了。
更进一步…… 还可以提供一些让客户代码扩展的机制,让它自己定义%后的转义符,以及处理方式。
3
我的意思是,这种方式是行不通的。
你要插入的元素是T吧?
std::set<std::list<T> > 元素是 std::list<T> 哦, 不是T了。
比较也是按std::less<std::list<T> >比较,而不是T。
不管multiset的底层实现是rbtree还是rbtree+list,都需要真正定义一个类,将底层实现的接口adapt一下才行。仅仅typedef是不够的……
回复 更多评论