从模板化非类型模板参数推导模板参数

时间:2019-05-28 19:51:17

标签: c++ visual-c++ template-deduction

我有以下typedef:

template<typename G, typename T, typename R>
using my_func_type = typename R(T::*)(G, int) const;

这是我经常使用的成员函数,因此我正在尝试制作不同的包装器。前提是我想要一个对象,可以通过通用函数调用来实现这些功能,以便可以以不同的方式组合它们(当前,我使用将调用包装为lambda的直接方法)。

但是,另一种方法是将该函数作为非类型模板参数传递(与lambda解决方案相比,由于我不断对其进行评估,因此提高了我的性能),即。

template<typename G, typename T, typename R, my_func_type<G, T, R> f>
struct MyWrapper
{
    MyWrapper(G g, T t) : g{ g }, t{ t } {}
    auto eval(int n) const
    {
        return (t.*f)(g, n);
    }

protected:
    G g;
    T t;
};

int main()
{
    AnObject g;
    TheCallingObject t;
    auto f = &TheCallingObject::callit;

    MyWrapper<AnObject, TheCallingObject, double, f> wrap(g, t)
}

但这似乎有点多余,因此可以从f推导出模板参数吗?

我找到的中途解决方案是:

template<auto f, typename G, typename T>
struct MyWrapper
{
    OpFuncDerivative(G g, T t) : g{ g }, t{ t } {}
    auto eval(int n) const
    {
        return (t.*f)(g, n);
    }

protected:
    G g;
    T t;
};

int main()
{
    AnObject g;
    TheCallingObject t;
    auto f = &TheCallingObject::callit;

    // it won't automatically deduce AnObject and TheCallingObject 
    // through the parameters to the constructor though!
    MyWrapper<f, AnObject, TheCallingObject> wrap(g, t) 
}

1 个答案:

答案 0 :(得分:1)

您可以编写一个辅助函数:

template<typename G, typename T, auto f>
struct MyWrapper
{
    MyWrapper(G g, T t) : g{g}, t{t}
    {}

    auto eval(int n) const
    {
       return (t.*f)(g, n);
    }

protected:
    G g;
    T t;
};

template<auto f, typename G, typename T>
MyWrapper<G, T, f> make_wrapper(G g, T t)
{
    return {g, t};
}

然后像这样使用它:

int main()
{
    AnObject g;
    TheCallingObject t;
    constexpr auto f = &TheCallingObject::callit;

    auto wrap = make_wrapper<f>(g, t);
}