0

我有以下课程:

    class Document
    {
    public:
        Document():
         // default values for members, 
         // ...
         m_dirty{false}{}

        // Accessor functions

        template<class OutputStream>
        Document& save(OutputStream stream)
        {
            // Write stuff to `stream`
            // ...

            m_dirty = false;
            return *this;
        }

        bool dirty() const { return m_dirty; }

    private:
        Size2d m_canvas_size;
        LayerStack m_layers;
        LayerIndex m_current_layer;

        std::vector<Palette> m_palettes;
        PaletteIndex m_current_palette;
        ColorIndex m_current_color;

        std::vector<std::string> m_palette_names;
        std::vector<std::string> m_layer_names;

        bool m_dirty;
    };

该类是否应该具有用于​​直接修改say m_palettes 元素的公共成员函数,例如

Document& color(PaletteIndex, ColorIndex, Color)

,或者更“正确”,只允许通过一对API访问整个向量:s

std::vector<Palette> const& palettes();
Document& palettes(std::vector<Palette>&&);

第一个选项会更有效,因为它不需要创建数据成员的临时副本,但始终使用这种设计会使接口变得臃肿。对于类中的每个容器,它都需要“深度”的 getter 和 setter。

注意脏标志。因此,以下内容会破坏抽象:

std::vector<Palette>& palettes();
4

2 回答 2

0

您可能有代理从调色板修改中“传播”脏标志,例如:

template <typename T>
class DirtyProxy
{
    T& data;
    bool& dirty;
public:
    DirtyProxy(T& data, bool& dirty) : data(data), dirty(dirty) {}
    ~DirtyProxy() { dirty = true;}
    DirtyProxy(const DirtyProxy&) = delete;

    T* operator ->() { return data; }
};

接着

DirtyProxy<Palette> palette(std::size_t i) { return {m_palettes.at(i), dirty}; }
于 2020-07-15T19:09:26.640 回答
0

我认为解决它最可靠的方法是使用回调。代理的一个问题是它无法处理客户端代码抛出异常的情况(假设有很强的异常保证)。测试用例:

try
{
    auto property_proxy = obj.getProperty();
    // an exception is thrown here...
    property_proxy->val = x;  // Never updated

}
catch(...)
{}

assert(!obj.dirty());

将失败,因为 dtor 总是设置脏标志。但是有一个回调

class Foo
{
    public:
        template<class F>
        Foo& modifyInSitu(F&& f)
        {
            f(x);
            m_dirty = true;
            return *this
        }
};

只会更新m_dirty,当f(x)不抛出。

于 2020-07-16T14:37:44.207 回答