Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factory method in base access protected ctor in derived

I want to all objects that derive from Initable to call terminate() on destruction. For this I create a shared_ptr with custom deleter.

My problem is that I cannot access the protected ctor of derived classes in order to create the instance in Initable factory method.

The ctor should be protected in order to prevent creation of instances without using the factory method.

class Initable {
public:
    virtual void terminate() = 0;

    template<typename T, typename... Ts>
    static shared_ptr<T> make_initable(const Ts &... args) {
        return shared_ptr<T>(new T(std::forward<const Ts>(args)...), [] (Initable * aptr) {
            cout << "custom deleter" << endl;
        });
    }
};

class B : public Initable {
    friend class Initable;
// ...
};

I would like to avoid declaring as friend every derived class, what can I do?

like image 884
alexyav Avatar asked Sep 22 '14 14:09

alexyav


1 Answers

Friendships are not:

  • symmetric.
  • transitive.
  • inherited.

This I think leaves you with the option to help your user in finding out he missed declaring the friendship to the Initable class. You cannot use template specialization for this as friend declaration needs to happen within the class scope and template declaration needs to happen in a namespace scope.

One way to do it would be:

#define DECLARE_INITABLE \
    constexpr static bool is_Initable_friend = true;\
    friend class Initable;

class Initable {
public:
     virtual void terminate() = 0;

     template<typename T, typename... Ts>
     static shared_ptr<T> make_initable(const Ts &... args) {
        static_assert(T::is_Initable_friend, "Please call DECLARE_INITABLE in your class   declaration");

        return shared_ptr<T>(new T(std::forward<const Ts>(args)...), [] (Initable * aptr) {
             cout << "custom deleter" << endl;
        });
     } 
};

class B : public Initable {
//  DECLARE_INITABLE
     ...
};
like image 83
da_m_n Avatar answered Nov 09 '22 18:11

da_m_n