首页 > 解决方案 > 将模板化参数包传递给回调函数(也是模板化函数)

问题描述

目前在我的代码中,我有一个函数,它接受各种参数和一个回调对象(它是一个带有 Callback(void) 函数的简单类的实例)。这现在工作得很好,但是它使代码混乱,因为我有很多这样的类,而且在大多数类中,它们的变量仅由 Callback() 函数使用。

我想用简单的函数替换这些类,如下所示:

#include <iostream>
#include <string>

template<class T>
class TestClass {
public:
    template<typename ...TArgs>
    using CallbackFuncType = bool(T &Data, TArgs && ...Args);

    TestClass(const T &Data) : data(Data) {}

    template<typename ...TArgs>
    bool Function(
        CallbackFuncType<TArgs...> Callback,
        TArgs && ...Args
    )
    {
        return Callback(data,
            std::forward<TArgs>(Args)...);
    }

private:
    const T data;
};

struct DataType {
    int valInt;
    double valFloat;

    std::string ToString()
    {
        return std::string(
            "valInt: " + std::to_string(valInt) +
            "valFloat: " + std::to_string(valFloat)
        );
    }
};

bool CBFunction1(DataType &Data, int Arg0, const std::string &Arg1)
{
    std::cout << "Data :" << Data.ToString() << std::endl;

    std::cout << "CBFunction1: " <<
        "Arg0 : " << Arg0 <<
        "Arg1: " << Arg1 <<
        std::endl;

    return true;
}

bool CBFunction2(DataType &Data, int Arg0, double Arg1, const std::string &Arg2)
{
    std::cout << "Data :" << Data.ToString() << std::endl;

    std::cout << "CBFunction2: " <<
        "Arg0 : " << Arg0 <<
        "Arg1: " << Arg0 <<
        "Arg2: " << Arg2 <<
        std::endl;

    return true;
}

int main()
{
    DataType data;
    data.valInt = 1;
    data.valFloat = 1.2;

    TestClass<DataType> testObj(data);

    std::cout << "test" << std::endl;

    std::cout << "call CBFunction1" << std::endl;
    bool val1 = testObj.Function(CBFunction1, 11, "test_string");
    bool val2 = testObj.Function(CBFunction2, 11, 111.111, "test_string");

    return 0;
}

编译后出现以下错误:

1>main.cpp
1>main.cpp(75,24): error C2672: 'TestClass<DataType>::Function': no matching overloaded function found
1>main.cpp(75,64): error C2784: 'bool TestClass<DataType>::Function(bool (__cdecl *)(T &,TArgs &&...),TArgs &&...)': could not deduce template argument for 'bool (__cdecl *)(T &,TArgs &&...)' from 'bool (DataType &,int,const std::string &)'
1>        with
1>        [
1>            T=DataType
1>        ]
1>main.cpp(13): message : see declaration of 'TestClass<DataType>::Function'
1>main.cpp(76,24): error C2672: 'TestClass<DataType>::Function': no matching overloaded function found
1>main.cpp(76,73): error C2784: 'bool TestClass<DataType>::Function(bool (__cdecl *)(T &,TArgs &&...),TArgs &&...)': could not deduce template argument for 'bool (__cdecl *)(T &,TArgs &&...)' from 'bool (DataType &,int,double,const std::string &)'
1>        with
1>        [
1>            T=DataType
1>        ]
1>main.cpp(13): message : see declaration of 'TestClass<DataType>::Function'

我尝试将 type_identity_t 添加到 Args,但没有成功。

标签: c++c++11templatesfunction-pointersvariadic-templates

解决方案


template <typename... TArgs>
bool Function(CallbackFuncType<TArgs...> Callback, TArgs&&... Args)

有几个问题,主要是TArgs两者的推导应该完全相同。

问题

template <typename... TArgs>
using CallbackFuncType = bool(T& Data, TArgs&&... Args);

是它只能匹配具有(l 或 r 值)引用的参数的函数。

所以像

template <typename... TArgs>
using CallbackFuncType = bool(T&, TArgs...);

template <typename... TArgs, typename... Ts>
bool Function(CallbackFuncType<TArgs...>* Callback, Ts&& ...Args)
{
    return Callback(data, std::forward<Ts>(Args)...);
}

可以解决问题,但更简单(更通用)

template <typename Func, typename... Ts>
bool Function(Func Callback, Ts&& ...Args)
{
    return Callback(data, std::forward<Ts>(Args)...);
}

演示


推荐阅读