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实现),而无需修改该类型。您的第二种方法总是需要修改类型才能添加功能。

09-08 04:07