C++ 中的可变参数类模板

741 阅读2分钟

「这是我参与11月更文挑战的第 1 天,活动详情查看:2021最后一次更文挑战」。

接上一篇C++ 中的可变参数函数模板 其实不仅可以定义可变参的函数模板,可变参模板类也是可以定义的。

定义:可变参模板类是一个带可变模板参数的模板类

最近在学习 AE 的插件开发,里面有些例子也涉及到了可变参类模板,所以以下代码参考自 AE 的插件开发源码。

首先是(两段式的,即无前向声明)变参模板定义的结构体

/// @note 可变参模板定义结构体【基本定义】
template <typename ReturnType, typename... Arguments>
struct CallbackType
{
    /// @note 类型取别名 type: 原类型 function 封装 “可调用对象” 依赖模板提供的返回值和参数类型
    using type = std::function<void(ReturnType, Arguments...)>;
};

/// @note 偏特化可变参类型,无返回值【递归终止条件】
/// https://www.cnblogs.com/qicosmos/p/4325949.html
template <typename... Arguments>
struct CallbackType<void, Arguments...>
{
    using type = std::function<void(Arguments...)>;
};

接着,使用到以上二者的可变参模板类 Function 的定义代码如下, 说明详见代码注释

/// @note 可变参的模板定义类
template <typename ReturnType, typename... Arguments>
class Function : public AbstractFunction
{
    friend struct FunctionHelper<ReturnType, Arguments...>;

    using Signature = ReturnType(WINAPI *) (Arguments...); ///< 类型重定义:函数指针类型(签名)

    /// @note  对 (返回值为 void 的) CallbackType 中 type 类型取别名 BeforeCallback
    /// 这里 typename 的作用是标明 “嵌套依赖类型名” 
    /// 因为它是个类型而不是变量,而且依赖模板提供的(可变)参数
    using BeforeCallback = typename CallbackType<void, Arguments...>::type;
    /// @note  同上,只不过有指定返回值类型 ReturnType
    using AfterCallback = typename CallbackType<ReturnType, Arguments...>::type;

public:
    Function(const char * name);
    
    /// @note 可变参成员函数
    ReturnType operator()(Arguments&... arguments) const;
    ReturnType directCall(Arguments... arguments) const;

    /// @note 传入变量类型正是上面自定义的类型,本质上是个封装了 “可调用对象” 的 std::function 对象
    void setBeforeCallback(BeforeCallback callback);
    void clearBeforeCallback();
    void setAfterCallback(AfterCallback callback);
    void clearAfterCallback();

protected:
    BeforeCallback m_beforeCallback;
    AfterCallback m_afterCallback;
};

Function 类的具体实现代码如下,简化了一些比较复杂的干扰代码

template <typename ReturnType, typename... Arguments>
Function<ReturnType, Arguments...>::Function(const char * _name)
    : AbstractFunction{_name}
, m_beforeCallback{nullptr}
, m_afterCallback{nullptr}
{
}

template <typename ReturnType, typename... Arguments>
ReturnType Function<ReturnType, Arguments...>::operator()(Arguments&... arguments) const
{
   /// FunctionHelper 类的定义略(是分为有返回值【泛化】和无返回值【偏特化】的可变参模板类)
   auto myAddress = address();

    if (myAddress != nullptr)
    {
        if (isAnyEnabled(CallbackMask::Before | CallbackMask::After | CallbackMask::Logging))
        {
            /// @note 可变参数的传递方式,涉及了右值引用和完美转发
            /// 内部会根据情况调用我们先前封装的 可调用实体
            return FunctionHelper<ReturnType, Arguments...>().call(this, std::forward<Arguments>(arguments)...);
        }
        else
        {
            /// @note 同上
            return FunctionHelper<ReturnType, Arguments...>().basicCall(this, std::forward<Arguments>(arguments)...);
        }
    }
    else
    {
         if (isEnabled(CallbackMask::Unresolved))
         {
            unresolved();
         }

         return ReturnType();
    }
}

template <typename ReturnType, typename... Arguments>
ReturnType Function<ReturnType, Arguments...>::directCall(Arguments... arguments) const
{
   ///< FunctionHelper 定义略,同上
   return FunctionHelper<ReturnType, Arguments...>().basicCall(this, std::forward<Arguments>(arguments)...);
}

template <typename ReturnType, typename... Arguments>
void Function<ReturnType, Arguments...>::setBeforeCallback(BeforeCallback callback)
{
    m_beforeCallback = std::move(callback);
}

template <typename ReturnType, typename... Arguments>
void Function<ReturnType, Arguments...>::clearBeforeCallback()
{
    m_beforeCallback = nullptr;
}

template <typename ReturnType, typename... Arguments>
void Function<ReturnType, Arguments...>::setAfterCallback(AfterCallback callback)
{
    m_afterCallback = std::move(callback);
}

template <typename ReturnType, typename... Arguments>
void Function<ReturnType, Arguments...>::clearAfterCallback()
{
    m_afterCallback = nullptr;
}