Mixins和函数模板是向多种类型提供行为的两种不同方式,只要这些类型满足某些要求即可。
例如,假设我想编写一些代码,使我可以将一个对象保存到文件中,只要该对象提供了toString
成员函数(这是一个很愚蠢的示例,但是请耐心等待)。第一种解决方案是编写如下的功能模板:
template <typename T>
void toFile(T const & obj, std::string const & filename)
{
std::ofstream file(filename);
file << obj.toString() << '\n';
}
...
SomeClass o1;
toFile(o1, "foo.txt");
SomeOtherType o2;
toFile(o2, "bar.txt");
另一种解决方案是使用CRTP使用mixin:
template <typename Derived>
struct ToFile
{
void toFile(std::string const & filename) const
{
Derived * that = static_cast<Derived const *>(this);
std::ofstream file(filename);
file << that->toString() << '\n';
}
};
struct SomeClass : public ToFile<SomeClass>
{
void toString() const {...}
};
...
SomeClass o1;
o.toFile("foo.txt");
SomeOtherType o2;
o2.toFile("bar.txt");
这两种方法的优缺点是什么?有没有受到青睐的人,如果是,为什么?
最佳答案
第一种方法更加灵活,因为可以使其与任何提供任何方式转换为std::string
的类型一起工作(可以使用traits-class实现),而无需修改该类型。您的第二种方法总是需要修改类型才能添加功能。