Files
external_libcamera/include/libcamera/base/class.h
Laurent Pinchart 33dd4fab9d libcamera: base: class: Don't pass Extensible pointer to Private constructor
The Extensible and Extensible::Private classes contain pointers to each
other. These pointers are initialized in the respective class's
constructor, by passing a pointer to the other class to each
constructor. This particular construct reduces the flexibility of the
Extensible pattern, as the Private class instance has to be allocated
and constructed in the members initializer list of the Extensible
class's constructor. It is thus impossible to perform any operation on
the Private class between its construction and the construction of the
Extensible class, or to subclass the Private class without subclassing
the Extensible class.

To make the design pattern more flexible, don't pass the pointer to the
Extensible class to the Private class's constructor, but initialize the
pointer manually in the Extensible class's constructor. This requires a
const_cast as the o_ member of the Private class is const.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2021-08-03 23:05:08 +03:00

112 lines
2.1 KiB
C++

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2020, Google Inc.
*
* class.h - Utilities and helpers for classes
*/
#ifndef __LIBCAMERA_BASE_CLASS_H__
#define __LIBCAMERA_BASE_CLASS_H__
#include <memory>
namespace libcamera {
#ifndef __DOXYGEN__
#define LIBCAMERA_DISABLE_COPY(klass) \
klass(const klass &) = delete; \
klass &operator=(const klass &) = delete;
#define LIBCAMERA_DISABLE_MOVE(klass) \
klass(klass &&) = delete; \
klass &operator=(klass &&) = delete;
#define LIBCAMERA_DISABLE_COPY_AND_MOVE(klass) \
LIBCAMERA_DISABLE_COPY(klass) \
LIBCAMERA_DISABLE_MOVE(klass)
#else
#define LIBCAMERA_DISABLE_COPY(klass)
#define LIBCAMERA_DISABLE_MOVE(klass)
#define LIBCAMERA_DISABLE_COPY_AND_MOVE(klass)
#endif
#ifndef __DOXYGEN__
#define LIBCAMERA_DECLARE_PRIVATE() \
public: \
class Private; \
friend class Private; \
template <bool B = true> \
const Private *_d() const \
{ \
return Extensible::_d<Private>(); \
} \
template <bool B = true> \
Private *_d() \
{ \
return Extensible::_d<Private>(); \
}
#define LIBCAMERA_DECLARE_PUBLIC(klass) \
friend class klass; \
using Public = klass;
#define LIBCAMERA_O_PTR() \
_o<Public>();
#else
#define LIBCAMERA_DECLARE_PRIVATE()
#define LIBCAMERA_DECLARE_PUBLIC(klass)
#define LIBCAMERA_O_PTR()
#endif
class Extensible
{
public:
class Private
{
public:
Private();
virtual ~Private();
#ifndef __DOXYGEN__
template<typename T>
const T *_o() const
{
return static_cast<const T *>(o_);
}
template<typename T>
T *_o()
{
return static_cast<T *>(o_);
}
#endif
private:
/* To initialize o_ from Extensible. */
friend class Extensible;
Extensible *const o_;
};
Extensible(Private *d);
protected:
template<typename T>
const T *_d() const
{
return static_cast<const T *>(d_.get());
}
template<typename T>
T *_d()
{
return static_cast<T *>(d_.get());
}
private:
const std::unique_ptr<Private> d_;
};
} /* namespace libcamera */
#endif /* __LIBCAMERA_BASE_CLASS_H__ */