【问题标题】:passing overloaded function pointer as argument to overloaded template function将重载函数指针作为参数传递给重载模板函数
【发布时间】:2017-12-27 14:26:38
【问题描述】:

我试图让编译器推断出正确的函数模板。 给定以下代码,推导出正确的模板函数...

class TestBase{};

template <typename c, typename RT, typename T0>
inline void CallF( RT( c::*M )(T0), TestBase* pObject, std::vector<OVariant> args )
{
    //safely convert variant (implementations external to class)
    T0 t0 = args[0].GetSafe<T0>();

    ((static_cast<c*>(pObject))->*M)(t0);
}

template <typename c, typename RT, typename T0, typename T1>
inline void CallF( RT( c::*M )(T0, T1), TestBase* pObject, std::vector<OVariant> args )
{
    //safely convert variant (implementations external to class)
    T0 t0 = args[0].GetSafe<T0>();
    T1 t1 = args[1].GetSafe<T1>();

    ((static_cast<c*>(pObject))->*M)(t0, t1);
}

class Test : public TestBase
{
public:

    void F( s32 one )
    {
        std::cout << "one";
    }

    struct Wrapped_F
    {
        //OVariant is my typical variant class
        static void Call( TestBase* pObject, std::vector<OVariant> args )
        {
            ::CallF<Test>( &Test::F, pObject, args );
        }
    };
};

int main(int argc, char *argv[])
{
    Test t;
    OVariant i( 13 );
    std::vector<OVariant> args;
    args.push_back( i );

    t.Wrapped_F::Call( &t, args );
}

t.Wrapped_F::Call( &t, args ) 调用正确的 F 函数。但是,如果我将重载的 F 函数添加到 Test,那么它将被调用(使用 2 个 args 重载)(而不是使用 1 个 args 的正确 F)

void F( s32 one, s32 two )
{
    std::cout << "two";
}

我很确定这是因为编译器没有足够的信息来推断。如何帮助编译器推断要调用哪个重载模板函数?

类似于下面的伪代码...(? 表示一些未知类型的 arg)

static void Call( TestBase* pObject, std::vector<OVariant> args )
{
    //Note: I won't know anything about the arguments to function F; I do know the size of the vector
    switch ( args.size() )
    {
    case 1:::CallF<Test,void,?>( &Test::F, pObject, args );
    case 2:::CallF<Test,void,?,?>( &Test::F, pObject, args );
    }
}

有没有办法做到这一点?

【问题讨论】:

    标签: c++ templates overloading template-argument-deduction


    【解决方案1】:

    编译器无法知道变量类中存储了什么。因此,? 可以从函数类型(从它的参数)中推断出来。因此,您将需要一些代码来检查 args.size() 是否与函数参数的数量匹配。尝试执行以下操作:

    • 创建std::tuple&lt;Args...&gt;,其中Args...是根据函数类型求值的
    • 检查args.size() 是否与std::tuple&lt;Args...&gt; 中的元素数相同
    • 将您的args 向量转换为元组。
    • 使用std::apply(或重新发明您自己的)使用元组中的参数调用您的函数

    【讨论】:

    • 我尝试了您的想法的变体,但它似乎不太合适。如果函数类型在 Call 函数中未知,那么创建 std::tuple 将如何工作?我会失去调用 OVariant::GetSafe (T0 t0 = args[0].GetSafe();) 的能力吗
    猜你喜欢
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    相关资源
    最近更新 更多