Const constructor

后端 未结 1 1398
太阳男子
太阳男子 2021-01-14 08:55

Is it possible in C++ to achieve something like a constructor that is only allowed to create const objects?

I am thinking of making a decorator class to

相关标签:
1条回答
  • 2021-01-14 09:49

    I only was able to get this working by having not a constructor that returns const object, but a static function (a-la named constructor) that returns shared_ptr<const decorator>. This 'encodes' constness in type and prohibits non-const calls:

    struct A
    {
        virtual void foo();         // requires non-const A
        virtual void bar() const;   // const method
    };
    
    class decorator : public A
    {
    private:
        std::shared_ptr<A> p_impl;
    public:
        virtual void foo()          { p_impl->foo(); }
        virtual void bar() const    { p_impl->bar(); }
    
        // regular constructor
        decorator(std::shared_ptr<A> const & p)             : p_impl(p) {} 
    
        static std::shared_ptr<decorator const> constDecorator(std::shared_ptr<A const> const & p) { return std::make_shared<decorator>(std::const_pointer_cast<A>(p)); } 
    };
    
    void F(std::shared_ptr<A> const       & regular_a
         , std::shared_ptr<A const> const & const_a   )
    {
        decorator regular_decorator(regular_a);
        regular_decorator.foo(); // all good
        regular_decorator.bar(); // all good
    
        decorator bad_decorator(const_a);   // compiler error
        // trying to use a const constructor to init a non-const object
    
        std::shared_ptr<const decorator> const_decorator = decorator::constDecorator(const_a); // all good
        const_decorator->foo(); // compiler error, foo is not const
        const_decorator->bar(); // all good
    
        // I have a lot of these in code that is beyond my control
        decorator bad_practice(const_cast<decorator&>(*const_decorator));
        bad_practice.foo(); // all good
    }
    

    You can of course use shared_ptr for non-const decorators too by declaring another static function and thus get similar usage patterns for both const and non-const.

    Note that this will require you to delete copy constructor and operator= for decorator, as they will lose constness. However, a similar problem exists in your version with a hypothetical const constructor.

    Another approach that I have tried was to make decorator a template class and have two different types: decorator<A> and decorator<const A>, hoping that compiler will not instantiate decorator<const A>::foo() unless it is used, but it keeps instantiating it even if it is not used.

    0 讨论(0)
提交回复
热议问题