指向成员函数 Class 类型的指针
Pointer to Member Function Class Type
class Object
{
public:
void mem_func();
}
我希望能够在编译时从指向成员函数 &Object::mem_func
的指针中提取类型 Object
,但没有注意到 <type_traits>
中的任何内容可用于获取类型。
这是一个 Pimpl class 所需要的,它有一个抽象数据成员,稍后将根据其 public class 将其转换为非抽象 class std::invoke
与
一起使用的层次结构
编辑: 应 Ilan Keshet 的要求,并且由于 Yakk - Adam Nevraumont 提出的解决方案无法通过我拥有的额外间接层工作。
下面是我正在尝试做的事情的更完整的想法。我想使用 Qt 的 QAbstractSlider 和 QSlider classes 来实现范围滑块 classes。也许我以错误的方式解决了问题,如果是这样,请指导我进行更好的设计 pattern/strategy 来完成此任务。
// RangeSlider.h
class AbstractRangeSliderPrivate;
class AbstractRangeSlider : public QWidget
{
Q_OBJECT
Q_DECLARE_PRIVATE_D(d_ptr_, AbstractRangeSlider)
public:
explicit AbstractRangeSlider(QWidget * parent = nullptr)
: QWidget(parent)
, d_ptr_(new AbstractRangeSliderPrivate{ this, new QAbstractSlider{ this }, new QAbstractSlider{ this } })
{}
virtual ~AbstractRangeSlider() override
{}
int minimum() const
{
Q_D(const AbstractRangeSlider);
return d->getTemplate(&QAbstractSlider::minimum);
}
void setMinimum(int min) const
{
Q_D(AbstractRangeSlider);
return d->setTemplate(&QAbstractSlider::setMinimum, min);
}
int maximum() const;
void setMaximum(int max);
//... etc
protected:
AbstractRangeSlider(AbstractRangeSliderPrivate & dd, QWidget * parent)
: QWidget(parent)
: d_ptr_(&dd)
{
}
QScopedPointer<AbstractRangeSliderPrivate> const d_ptr_;
};
class RangeSliderPrivate;
class RangeSlider : public AbstractRangeSlider
{
Q_OBJECT
Q_DECLARE_PRIVATE_D(d_ptr_, RangeSlider)
public:
RangeSlider(QWidget * parent = nullptr)
: AbstractRangeSlider(new RangeSliderPrivate{ this, QSlider{ this }, QSlider{ this } }, parent)
{
}
virtual ~RangeSlider() override
{
}
// These need to be cast from QAbstractSlider in the get/setTemplates
// since these member functions are only in the derived slider class.
QSlider::TickPosition tickPosition() const
{
Q_D(RangeSlider);
return d->getTemplate(&QSlider::tickPosition);
}
void setTickPosition(QSlider::TickPosition position)
{
Q_D(RangeSlider);
return d->setTemplate(&QSlider::setTickPosition, position);
}
// etc
};
// RangeSlider_p.h
#include "AbstractRangeSlider.h"
#include <QAbstractSlider>
#include <utility>
class AbstractRangeSliderPrivate
: public MixinPrivate<AbstractRangeSliderPrivate, QAbstractSlider>
{
Q_DECLARE_PUBLIC(AbstractRangeSlider)
public:
AbstractRangeSlider * q_ptr;
AbstractRangeSliderPrivate(AbstractRangeSlider * q)
: q_ptr(q)
{}
~AbstractRangeSliderPrivate()
{}
void init(QAbstractSlider * lowSlider, QAbstractSlider * highSlider_)
{
lowSlider_ = lowSlider;
highSlider_ = highSlider;
}
template <typename Func>
auto getTemplate(Func func) const
{
// I want to cast these from AbstractRangeSlider to a concrete type such as QSlider when necessary
assert(std::invoke(func, static_cast<???>(lowSlider_))) == std::invoke(func, static_cast<???>(highSlider_)));
return std::invoke(func, static_cast<???>(lowSlider_));
}
template <typename Func, typename... Args>
void setTemplate(Func func, Args && ... args)
{
std::invoke(func, static_cast<???>(lowSlider_)), std::forward<Args>(args)...);
std::invoke(func, static_cast<???>(highSlider_)), std::forward<Args>(args)...);
}
AbstractRangeSlider * lowSlider_;
AbstractRangeSlider * highSlider_;
};
template<auto x>
struct memfunc_object;
template<auto x>
using memfunc_object_t=typename memfunc_object<x>::type;
template<class T, class R, class...Args, R(T::*mf)(Args...)>
struct memfunc_object< mf > {
using type=T;
};
需要c++17。
没有它,你可以做decltype(&bob::hello)
并写一个类似的特征class来提取T
。
template<class M>
struct memfunc_t_object;
template<class M>
using memfunc_t_object_t=typename memfunc_t_object<M>::type;
template<class T, class R, class...Args>
struct memfunc_t_object< R(T::*)(Args...) > {
using type=T;
};
class Object
{
public:
void mem_func();
}
我希望能够在编译时从指向成员函数 &Object::mem_func
的指针中提取类型 Object
,但没有注意到 <type_traits>
中的任何内容可用于获取类型。
这是一个 Pimpl class 所需要的,它有一个抽象数据成员,稍后将根据其 public class 将其转换为非抽象 class std::invoke
与
编辑: 应 Ilan Keshet 的要求,并且由于 Yakk - Adam Nevraumont 提出的解决方案无法通过我拥有的额外间接层工作。
下面是我正在尝试做的事情的更完整的想法。我想使用 Qt 的 QAbstractSlider 和 QSlider classes 来实现范围滑块 classes。也许我以错误的方式解决了问题,如果是这样,请指导我进行更好的设计 pattern/strategy 来完成此任务。
// RangeSlider.h
class AbstractRangeSliderPrivate;
class AbstractRangeSlider : public QWidget
{
Q_OBJECT
Q_DECLARE_PRIVATE_D(d_ptr_, AbstractRangeSlider)
public:
explicit AbstractRangeSlider(QWidget * parent = nullptr)
: QWidget(parent)
, d_ptr_(new AbstractRangeSliderPrivate{ this, new QAbstractSlider{ this }, new QAbstractSlider{ this } })
{}
virtual ~AbstractRangeSlider() override
{}
int minimum() const
{
Q_D(const AbstractRangeSlider);
return d->getTemplate(&QAbstractSlider::minimum);
}
void setMinimum(int min) const
{
Q_D(AbstractRangeSlider);
return d->setTemplate(&QAbstractSlider::setMinimum, min);
}
int maximum() const;
void setMaximum(int max);
//... etc
protected:
AbstractRangeSlider(AbstractRangeSliderPrivate & dd, QWidget * parent)
: QWidget(parent)
: d_ptr_(&dd)
{
}
QScopedPointer<AbstractRangeSliderPrivate> const d_ptr_;
};
class RangeSliderPrivate;
class RangeSlider : public AbstractRangeSlider
{
Q_OBJECT
Q_DECLARE_PRIVATE_D(d_ptr_, RangeSlider)
public:
RangeSlider(QWidget * parent = nullptr)
: AbstractRangeSlider(new RangeSliderPrivate{ this, QSlider{ this }, QSlider{ this } }, parent)
{
}
virtual ~RangeSlider() override
{
}
// These need to be cast from QAbstractSlider in the get/setTemplates
// since these member functions are only in the derived slider class.
QSlider::TickPosition tickPosition() const
{
Q_D(RangeSlider);
return d->getTemplate(&QSlider::tickPosition);
}
void setTickPosition(QSlider::TickPosition position)
{
Q_D(RangeSlider);
return d->setTemplate(&QSlider::setTickPosition, position);
}
// etc
};
// RangeSlider_p.h
#include "AbstractRangeSlider.h"
#include <QAbstractSlider>
#include <utility>
class AbstractRangeSliderPrivate
: public MixinPrivate<AbstractRangeSliderPrivate, QAbstractSlider>
{
Q_DECLARE_PUBLIC(AbstractRangeSlider)
public:
AbstractRangeSlider * q_ptr;
AbstractRangeSliderPrivate(AbstractRangeSlider * q)
: q_ptr(q)
{}
~AbstractRangeSliderPrivate()
{}
void init(QAbstractSlider * lowSlider, QAbstractSlider * highSlider_)
{
lowSlider_ = lowSlider;
highSlider_ = highSlider;
}
template <typename Func>
auto getTemplate(Func func) const
{
// I want to cast these from AbstractRangeSlider to a concrete type such as QSlider when necessary
assert(std::invoke(func, static_cast<???>(lowSlider_))) == std::invoke(func, static_cast<???>(highSlider_)));
return std::invoke(func, static_cast<???>(lowSlider_));
}
template <typename Func, typename... Args>
void setTemplate(Func func, Args && ... args)
{
std::invoke(func, static_cast<???>(lowSlider_)), std::forward<Args>(args)...);
std::invoke(func, static_cast<???>(highSlider_)), std::forward<Args>(args)...);
}
AbstractRangeSlider * lowSlider_;
AbstractRangeSlider * highSlider_;
};
template<auto x>
struct memfunc_object;
template<auto x>
using memfunc_object_t=typename memfunc_object<x>::type;
template<class T, class R, class...Args, R(T::*mf)(Args...)>
struct memfunc_object< mf > {
using type=T;
};
需要c++17。
没有它,你可以做decltype(&bob::hello)
并写一个类似的特征class来提取T
。
template<class M>
struct memfunc_t_object;
template<class M>
using memfunc_t_object_t=typename memfunc_t_object<M>::type;
template<class T, class R, class...Args>
struct memfunc_t_object< R(T::*)(Args...) > {
using type=T;
};