处理数据观察者类的常量和非常量版本

时间:2017-11-09 09:24:00

标签: c++ oop templates generic-programming

在设计数据观察类(如迭代器)时,我一直遇到同样的问题,关于const和非const版本的处理和转换。

考虑一个通过指针或类似方法观察一些外部处理数据的类(类似于std::weak_ptr):

template<typename T>
class observer {
public:
    observer(T* ptr) :
        _ptr(ptr) {}

    T& get() const {
        return *_ptr;
    }

private:
    T* _ptr;
};

除了你只想要访问观察到的数据的时候,这一切都很酷而且花花公子:

template<typename T>
void need_const(observer<T const>) {}

// Uh oh...
observer<int> o{ nullptr };
need_const(o);    // Can't do

显然会丢失对const版本的隐式转换,例如所有基本类型(int -> int constT* -> T const*等)。关于如何解决这个问题,我有几个想法,但它们似乎都不理想,我想知道这个问题的C ++风格解决方案是什么样的。

  • observer<T>接受observer<U>的转换构造函数。对于某些情况(并且实际上是std::weak_ptr中使用的情况)可以正常工作,但显然它会创建一个新对象。它不适用于任何想要通过左值引用访问对象的东西,例如 template<typename T> void need_const(observer<T const>&) {}

  • 而是使用两个类observer<T>const_observer<T>,它们分别具有非const和const指针,用于观察数据。这类似于标准库执行迭代器的方式。这仍然无法解决上述问题,导致更多选择如何设计:

    • observer<T>包含const_observer<T>,使用const_cast来允许非const访问,并为const访问实现operator const_observer<T>&()转换。完美无缺,除了使用const_cast让我感到狡猾和不优雅。

    • observer<T>继承自const_observer<T>,使用const_cast来允许非const访问。同样,这种方法很有效,除了它引入了继承,这是另一个完整的鱼群。

  • 我没有考虑的事情。

0 个答案:

没有答案