首页 > 解决方案 > C++11 简化了调用同一模板函数的不同特化的模板函数的语法

问题描述

有几个模板函数(具有相同的签名),例如:

template <typename T, typename P> void f1(T t, P p);
template <typename T, typename P> void f2(T t, P p);

还有一些具有相同逻辑的函数用不同的谓词调用它们:

template <typename T> void g1(T t)
{
    f1(t, Pred1{});
    ...
    f1(t, Pred2{});
    ...
}

// same as g1 but calls f2 instead of f1
template <typename T> void g2(T t)
{
    f2(t, Pred3{});
    ...
    f2(t, Pred4{});
    ...
}

我试图概括它们,我能想出的只是:

template <typename P1, typename P2, typename FP1, typename FP2, typename T>
void g(T t, FP1 fp1, FP2 fp2, P1 p1, P2 p2)
{
    fp1(t, p1);
    ...
    fp2(t, p2);
    ...
}

template <typename T> void g1(T t)
{
    g(t, f1<T, P1>, f2<T, P2>, P1{}, P2{});
}

所以它过于冗长,尤其是对于真实类型,而不是本例中的玩具类型。我必须分别传递f()在泛化函数中调用的每个特化g(),并且我必须两次提及每个谓词(首先,它在 f 特化中的类型,第二,谓词对象作​​为单独的参数)。

如果我从中删除P1 p1, P2 p2参数g(),我仍然必须这样称呼它:g<P1, P2>(t, f1<T, P1>, f1<T, P2>)

有没有办法让它更简单并避免重复?

我仅限于 C++11/14。

标签: c++c++11templates

解决方案


您不能有模板模板函数参数。

传递重载的方法是将它们包装在 Functor 中。

所以你的泛型g变成:

template <typename F, typename T>
void g(F f, T t)
{
    f(t, Pred1{});
    ...
    f(t, Pred2{});
    ...
}

使用泛型 lambda 在 C++14 中创建仿函数更容易:

g([](auto e, auto pred){ return f1(e, pred); }, t);

在 C++11 中,仿函数更冗长(尤其是捕获):

struct F1
{
    template <typename T, typename Pred>
    auto operator()(T t, Pred pred) const {
        return f1(t, pred);
    }
};

g(F1{}, t);

推荐阅读