简体   繁体   中英

Pointer to Member Function Class Type

class Object
{
public:
    void mem_func();
}

I want to be able to extract the type Object at compile time from a pointer to member function &Object::mem_func , but did not notice anything in <type_traits> that could be used to get the type.

This is desired for a Pimpl class that has an abstract data member that would cast it to a non-abstract class later depending on its public class hierarchy to use std::invoke with.


Edit: at the request of Ilan Keshet and since Yakk - Adam Nevraumont's proposed solution isn't working through the extra layer of indirection that I have.

Below is a more complete idea of what I am trying to do. I wanted to use Qt's QAbstractSlider and QSlider classes to implement range slider classes. Maybe I am approaching the problem in the wrong way, and if so please direct me to a better design pattern/strategy to accomplish this.

// 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;
};

live example .

Requires .

Without it, you can do decltype(&bob::hello) and write a similar trait class to extract 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;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM