Шаблон для привязки не являющейся членом функции c вместе с функцией-членом - PullRequest
0 голосов
/ 06 августа 2020

У меня есть класс, который хранит отправленные команды в очереди и вызывает их позже. Командный процессор - это шаблонный класс Encoder, он использует свой метод Encoder::Encode для обработки команды. Но это может быть как член, так и статическая c функция, не являющаяся членом. Как его привязать?

// specialization that have deduced Encoder's arguments
template <class Encoder, typename ... ArgsT>
class SerialCommunicator<Encoder, std::tuple<ArgsT...>>
{

    // ...
    Encoder encoder_;
    std::queue<std::function<EncodeResult(QByteArray&)> commands_;
    mutable std::mutex commandsMutex_;

public:
    // ...

    void Dispatch(ArgsT ... args)
    {
        std::lock_guard<std::mutex> lg{commandsMutex_};
        commands_.emplace(std::bind(&Encoder::Encode, &encoder_, std::placeholers::_1, 
                std::forward<ArgsT>(args)...);
    }

    // ...
};

В C ++ 17 я мог бы использовать блок if constexpr(std::is_member_function_pointer_v<&Encoder::Encode>) для передачи указателя на Encoder в случае, если мы имеем дело с указатель на функцию-член.

1 Ответ

0 голосов
/ 06 августа 2020

Не очень элегантное решение с использованием SFINAE

template<typename FuncPtr, typename T,
        bool = std::is_member_function_pointer<FuncPtr>::value>
struct bind_func
{
    template<typename ... Args>
    static auto bind(FuncPtr fPtr, T *pObj, Args &&... args)
    {
        return std::bind(fPtr, std::forward<Args>(args)...);
    }
};

template<typename FuncPtr, typename T>
struct bind_func<FuncPtr, T, true>
{
    template<typename ... Args>
    static auto bind(FuncPtr fPtr, T *pObj, Args &&... args)
    {
        return std::bind(fPtr, pObj, std::forward<Args>(args)...);
    }
};

template<typename FuncPtr, typename T, typename ... Args>
auto bind_func_v(FuncPtr funcPtr, T *pObj, Args &&... args)
{
    return bind_func<FuncPtr, T>::bind(funcPtr,
                    pObj, std::forward<Args>(args)...);
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...